Molog

Un interpréteur prolog pour mots

Bases

Langages, algorithmes...

Langage

Constantes : symboles commencant par une minuscule

Variables : symboles commencant par une majuscule

Terme : constante, variable ou symbole de fonction d'arité.

Atome : si p est un symbole de prédicat, p/n est un atome

Littéral : un atome, sa négation

Clause : une clause se note par Atome1<Atome2;Atome3... .

Substitution : on note une substitution par { Variable/Terme; Variable/Terme ... }

Algorithme général

Saisie d'un ensemble de clauses.

Saisie d'un but à prouver

etape1 :

Si (But vide)

{

Afficher la substitution courante;

Demander à forcer le Backtrack ?

Si oui, retourner au dernier point de choix;

Sinon Fin = Vrai;

}

Sinon

etape2 :

Examiner si il y a des clauses non explorées pour le predicat But

Si il y en a la prendre;

Si il y en a d'autres les formaliser dans un point de choix;

etape4 :

Si le But s'unifie à la clause par la substitution S

{

Changer la substitution courante par S;

Renommer la substitution S.

Substituer le But et la Clause par S;

Enlever le premier atome du but;

Et rajouter en début du But la suite des atomes de la clause prouvée.

aller en etape1

}

Sinon

aller en étape5

etape5 :

Si il y a encore des clauses non explorées

{

Marqué le choix courant;

Reprendre le but, avec une clause non exploitée;

aller en etape1

}

Sinon

{

Si il y a un pere au point de choix courant

{

Marquer le choix courant;

Prendre le point de choix pere;

Modifier le but, et la clause non exploitée;

retourner en etape6;

}

Sinon

{

Rien n'est prouver;

Fin = Faux ;

}

}

}

Algorithme d'unification (P1, P2)

etape0 :

Si le nom et l'arité des prédicats sont différents

retour Faux;

etape1 :

Initialisation de la substitution à Vide.

etape2 :

unif = FAUX

pour i de 1 a arite et tant que unif = VRAI

si (symbole de P1 != de symbole de P2)

unif = FAUX;

retour Vrai;

etape3 :

Si p1(i) est une variable et p2(i) est une constante

si on a une substitution p1(i)/k et k!=p2(i)

retour Faux;

sinon

si pas de subsitution pour p1(i)

Ajouter p1(i)/p2(i)

aller en etape2

Si p1(i) est une variable et p2(i) est une variable

si on a deux substitutions pour p1(i) et pour p2(i) différentes

retour Faux;

sinon aller en etape2

Si p1(i) est une fonction d'arité et p2(i) est une fonction d'arite

unifier p1(i) et p2(i) avec la substitution courante

si unification échoue : retour Faux;

sinon aller en etape2

Même tests en échangeant p1(i) par p2(i)

retour Faux;

Méthode de Renommage

Soit une substitution S

Pour tous les elements t/k de la substitution

si t et k contiennent une variable identique,

renommer k en k + 1

Méthode de substitution

Soit un prédicat P, et une substitution S

Pour tous les termes t du prédicat

si il existe dans la substitution la substitution t/k

remplacer t par k

Structure de données

Prédicats et substitution

 

Les différentes constantes :

MAXSYMB : maximum de symboles gérables

MAXARITE : nombre maximum de terme par prédicat.

VRAI

FAUX

Les différents éléments du langages :

typedef enum symbole { VAR, CON, FON } SYMB;

Un element de la table des symboles :

typedef struct elttab{

char * nom; /* la chaine correspondant au symbole */

SYMB typ; /* le type du symbole */

int indice; /* la valeur lors du renommage */

struct elttab * suiv; /* le symbole suivant dans la table */

} ELTTAB;

Une clause :

Structure

typedef struct clause {

char * nomclause;

int * arite;

ELTTAB sy;

struct clause * cons;

} CLAUSE;

Fonctions

/* Formatage d'une clause a partir d'une chaine */

CLAUSE * SaisieCLA (char * Chaine);

/* Libération d'une clause */

void LibereCLA( CLAUSE ** Clause);

/* Copier une Clause */

CLAUSE * CopieCLA(CLAUSE * Clause);

/* Concatener une clause a une autre */

void ConcatCLA(CLAUSE ** Clause1, CLAUSE * Clause2);

Une Substitution :

Structure

typedef struct Sub {

ELTTAB * Var; /* Variable */

ELTTAB * Val; /* Valeur */

struct Sub * suiv;

}SUB;

Fonctions

/* Ajouter un item de substitution */

void AjouterSUB(ELTTAB * Var, ELTTAB * Val, SUB ** Sub);

/* Liberer une subsitution */

void LibereSUB(SUB **Sub);

/* Copier une substitution */

SUB * CopieSUB(SUB * Sub);

/* Afficher une substitution */

void AfficherSUB(SUB * Sub);

/* renommage d'une substitution */

void RenommeSUB(SUB * Sub);

Un Point de Choix :

Structure

typedef struct PointDeChoix {

struct PointDeChoix * Pere ; /* Pere du point de choix */

CLAUSE * But; /* But a prouver dans le point de choix */

SUB * Sub; /* Substitution lors du point de choix */

struct PointDeChoix * liste ; /* Liste des points de choix fils */

struct PointDeChoix * suiv ; /* Choix frere a explorer */

}PDC;

Fonctions

/* Créer un Point de Choix */

PDC * CreatePDC( CLAUSE * But,

SUB * Sub,

PDC * Pere);

/* Utiliser un Point de Choix */

void UtiliserPDC( PDC * Pdc,

CLAUSE ** But,

SUB ** Sub,

CLAUSE ** Clause);

/* Liberer un Point de Choix */

void LiberePDC( PDC **Pdc);

Fonctions générales

/* renvoie la premiere clause et complete le point de choix */

CLAUSE * ExamimerClause( PDC * Pdc,

CLAUSE * But,

CLAUSE Liste,

int nbClauses);

/* Substitution d'une Clause */

void Substitue(CLAUSE * Clause, SUB * Sub);

/* Evalue les conditions pour que deux fns d'arite soit unifiable */

SUB * isUnifiable(ELTTAB Sy1, ELTTAB Sy2);

/* Evalue les conditions pour que deux fns d'arite soit unifiable */

int ContradictionSUB(SUB ** Sub1,SUB * Sub2);

 

Algorithme Prouver

unification, preuve

int Prouver(CLAUSE * But, CLAUSE Liste, int NbClauses);

{

SUB * SubCourante;

CLAUSE * ClauseCourante;

PDC * PdcCourant;

CLAUSE * ButCourant;

etape1 :

if (But ==NULL)

{

AfficherSUB(SubCourante);

{

char c;

printf(" Bakctrack ?");

scanf("%c", &c);

if (toupper(c)=='0')

goto etape5 ;

}

return VRAI;

}

etape2 :

ClauseCourante = ExamimerClause(PdcCourant, But, Liste, nbClauses);

if (ClauseCourante==NULL)

goto etape5;

etape4 :

if (Unifie(But,Clause,&SubCourante)==VRAI)

{

RenommeSub(SubCourante);

Substitue(ClauseCourante, SubCourante);

Substitue(But, SubCourante);

But = But->cons;

ConcatePRED(Clause->cons,But->cons);

But = Clause->cons;

goto etape1 ;

}

etape5 :

if (PdcCourant->liste!=NULL)

{

PDC * PdcTemp;

PdcCourant = PdcCourant->liste;

Utiliser(PdcCourant, &ButCourant, &SubCourante,&ClauseCourante);

goto etape1;

}

else

if (PdcCourant->suiv!=NULL)

{

PDC * PdcTemp;

PdcTemp = PdcCourant;

PdcCourant = PdcCourant->suiv;

LiberePDC(PdcTemp);

Utiliser(PdcCourant, &ButCourant, &SubCourante,&ClauseCourante);

goto etape1;

}

else

if (PdcCourant->Pere!=NULL)

{

PDC * PdcTemp;

PdcTemp = PdcCourant;

PdcCourant = PdcCourant->pere;

LiberePDC(PdcTemp);

Utiliser(PdcCourant, &ButCourant, &SubCourante,&ClauseCourante);

goto etape1;

}

else

return FAUX ;

}

 

Algorithme Unifie

unification

int Unifie (CLAUSE * C1, CLAUSE * C2, SUB ** Sub);

{

ELTTAB * Sy1= C1->Sy;

ELTTAB * Sy2=C2->Sy;

etape0 :

if (strcmp(C1->nom, C2->nom)!=0)

return FAUX;

if (strcmp(C1->arite, C2->arite)!=0)

return FAUX;

etape1 :

LibereSUB(&(*Sub)); /* Met Sub à NULL */

etape2 :

unif = FAUX;

while (Sy1->suiv!=NULL && unif==VRAI)

{

if (strcmp(Sy1->nom,Sy2->nom)!=0)

{

unif = FAUX;

goto etape3 ;

}

Sy1= Sy1->suiv;

Sy2 = Sy2->suiv;

}

return VRAI;

typedef struct elttab{

char * nom; /* la chaine correspondant au symbole */

SYMB typ; /* le type du symbole */

int indice; /* la valeur lors du renommage */

struct elttab * suiv; /* le symbole suivant dans la table */

etape3 :

if ((Sy1->typ==VAR))

{

AjouterSUB(S1->nom, S2->nom, &Sub);

Substitue(C1, *Sub);

Substitue(C2,*Sub);

goto etape2 ;

}

if ((Sy1->typ==FON) && (Sy2->typ==FON))

{

SUB * SubUnif;

SUB * SubTemp2 = Sub;

SUB * SubTemp3;

SubUnif = isUnifiable(Sy1, Sy2);

if (SubUnif ==NULL)

return FAUX;

if (ContradictionSUB(&SubUnif,Sub)==VRAI)

return FAUX;

AjouterSUB(S1->nom, S2->nom, &Sub);

Substitue(C1, *Sub);

Substitue(C2,*Sub);

goto etape2 ;

}

if ((Sy1->typ==FON) && (Sy2->typ==CON))

return FAUX;

if ((Sy2->typ==VAR))

{

AjouterSUB(S1->nom, S2->nom, &Sub);

Substitue(C1, *Sub);

Substitue(C2,*Sub);

goto etape2 ;

}

if ((Sy2->typ==FON) && (Sy1->typ==FON))

{

SUB * SubUnif;

SUB * SubTemp2 = Sub;

SUB * SubTemp3;

SubUnif = isUnifiable(Sy2, Sy1);

if (SubUnif ==NULL)

return FAUX;

if (ContradictionSUB(&SubUnif,Sub)==VRAI)

return FAUX;

AjouterSUB(S1->nom, S2->nom, &Sub);

Substitue(C1, *Sub);

Substitue(C2,*Sub);

goto etape2 ;

}

return FAUX;

}