2009-12-09 3 views
3

J'ai besoin d'aide avec une routine que j'essaie de créer. Je dois faire une routine qui ressemble à quelque chose comme ceci:routine de différence Prolog

difference([(a,b),(a,c),(b,c),(d,e)],[(a,_)],X). 

X = [(b,c),(d,e)]. 

J'ai vraiment besoin d'aide sur celui-ci ..

J'ai écrit une méthode jusqu'à présent qui peut enlever la première occurrence qu'il trouve. Cependant, j'en ai besoin pour supprimer toutes les occurrences. Voici ce que j'ai jusqu'à présent ...

memberOf(A, [A|_]). 
memberOf(A, [_|B]) :- 
    memberOf(A, B). 

mapdiff([], _, []) :- !. 
mapdiff([A|C], B, D) :- 
     memberOf(A, B), !, 
     mapdiff(C, B, D). 
mapdiff([A|B], C, [A|D]) :- 
     mapdiff(B, C, D). 

J'ai pris ce code de la liste (soustraire).

Je ne comprends pas complètement ce qu'il fait, mais je sais que c'est presque ce que je veux. Je n'ai pas utilisé de soustraction car mon code final doit être compatible avec WIN-Prolog ... Je le teste sur SWI Prolog.

+0

Votre code fonctionne pour moi (dans SWI-Prolog et GNU-Prolog). Je ne connais pas WIN-Prolog, donc je ne peux pas vous aider là-bas. – Stephan202

+1

Eh bien cela fonctionne mais il ne supprime pas toutes les occurrences de A. Il supprime seulement le premier. – SteveW

+1

Vous avez raison. D'une certaine façon, j'avais l'air mal (?). Je pense que le problème est que la vérification des membres effectue l'unification, et par conséquent après le premier test '(a, _)' devient '(a, b)', qui ne correspondra plus à '(a, c)'. Je pense à une bonne solution ... – Stephan202

Répondre

2

Je ne suis pas sûr, mais quelque chose comme ça pourrait fonctionner. Vous pouvez utiliser findall pour trouver tous les éléments qui ne peuvent pas être unifié avec le motif:

?- findall(X, (member(X, [(a,b),(b,c),(a,c)]), X \= (a,_)), Res). 

obtient la réponse

Res = [ (b, c) ] 

Alors

removeAll(Pattern, List, Result) :- 
    findall(ZZ109, (member(ZZ109, List), ZZ109 \= Pattern), Result). 

devrait fonctionner, en supposant ZZ109 ISN » t une variable en Pattern (je ne connais pas un moyen d'obtenir une nouvelle variable pour cela, malheureusement, il y en a peut-être une non-portable dans WIN-Prolog). Et puis difference peut être défini de manière récursive:

difference(List, [], List). 
difference(List, [Pattern|Patterns], Result) :- 
    removeAll(Pattern, List, Result1), 
    difference(Result1, Patterns, Result). 
+2

ZZ109 est une nouvelle variable. En interne, Prolog modifie le nom de la variable. Ce ne sera la même variable que si vous utilisez explicitement ZZ109 dans la même clause. C'est-à-dire que le ZZ109 dans Pattern peut être renommé en interne en _123 alors que ZZ109 dans la clause de différence sera renommé _314. Rien à craindre là-bas .. Bonne solution cependant. – neXus

2

Votre code peut être facilement modifié pour fonctionner en faisant en sorte que le prédicat memberOF vérifie juste pour voir qu'il ya un élément dans la liste qui peut être unifiée sans en fait l'unifier. Dans SWI Prolog cela peut se faire de cette façon:

memberOf(A, [B|_]) :- unifiable(A,B,_). 

Mais je ne suis pas familier avec WIN-Prolog donc je ne sais pas si elle a un prédicat ou un opérateur qui vérifie uniquement si les arguments peuvent être unifiés.

3

Tricky one! humble café a la bonne idée. Voici une solution sophistiquée utilisant la double négation:

difference([], _, []). 
difference([E|Es], DL, Res) :- 
    \+ \+ member(E, DL), !, 
    difference(Es, DL, Res). 
difference([E|Es], DL, [E|Res]) :- 
    difference(Es, DL, Res). 

Fonctionne sur SWI-PROLOG. Explication:

Article 1: Cas de base. Rien à comparer contre!

Article 2: Si E est dans la liste de différence DL, le member/2 subgoal évalue à true, mais nous ne voulons pas accepter les liaisons qui member/2 fait entre les variables présentes dans les termes à la liste, comme nous aimerions Par exemple, la variable du terme (a,_) est réutilisable dans d'autres termes et n'est pas liée à la première solution. Ainsi, le 1er \+ supprime les liaisons de variables créées par une évaluation réussie de member/2, et le second \+ inverse l'état d'évaluation à true, selon les besoins.La coupure se produit après la vérification, à l'exclusion de la troisième clause, et en jetant l'élément unifiable. Clause 3: Conserver tout élément non unifiable entre les deux listes.