2017-01-08 2 views
1

Compte tenu des faits suivants:Prolog (Sicstus) - non membres et les questions SETOF

route(TubeLine, ListOfStations). 

route(green, [a,b,c,d,e,f]). 
route(blue, [g,b,c,h,i,j]). 
... 

Je suis obligé de trouver toutes les paires de tubes Les lignes qui n'ont pas de stations en commun, produisant les éléments suivants:

| ?- disjointed_lines(Ls). 
Ls = [(yellow,blue),(yellow,green),(yellow,red),(yellow,silver)] ? ; 
no 

je suis venu avec la réponse ci-dessous, mais il ne me donne pas seulement mauvaise réponse, mais il ne s'applique pas mon X^état - ie il encore imprime les résultats par membre des stations distingue:

disjointed_lines(Ls) :- 
         route(W, Stations1), 
         route(Z, Stations2), 
         setof(
         (W,Z),X^ 
         (member(X, Stations1),nonmember(X, Stations2)), 
         Ls). 

C'est la sortie que la définition produit:

| ?- disjointed_lines(L). 
L = [(green,green)] ? ; 
L = [(green,blue)] ? ; 
L = [(green,silver)] ? ; 
... 

Je crois que ma logique relative à l'adhésion est incorrecte, mais je ne peux pas comprendre ce qui est faux. Quelqu'un peut-il voir où je vais échouer? J'ai également lu Learn Prolog Now chapitre 11 sur la collecte des résultats comme suggéré here, mais il semble que je suis toujours incapable d'utiliser correctement l'opérateur ^. Toute aide serait appréciée!


MISE À JOUR:

Comme suggéré par l'utilisateur CapelliC, j'ai changé le code dans les éléments suivants:

disjointed_lines(Ls) :- 
         setof(
         (W,Z),(Stations1, Stations2)^ 
         ((route(W, Stations1), 
         route(Z, Stations2),notMembers(Stations1,Stations2))), 
         Ls). 

notMembers([],_). 
notMembers([H|T],L):- notMembers(T,L), nonmember(H,L). 

qui suit, cependant, me donne des copies de (X, Y) et (Y, X), mais l'étape suivante consistera à supprimer ces éléments dans une règle distincte. Merci pour l'aide!

Répondre

2

Je pense que vous devriez mettre les appels route/2 à l'intérieur de setof 'goal, et exprimer la disjonction plus clairement, de sorte que vous pouvez le tester séparément. À propos de l'opérateur ^, il demande qu'une variable soit universellement quantifiée dans la portée de l'objectif. Peut-être une explication concise comme celle trouvée à bagof/3 page de manuel vous aidera ...

disjointed_lines(Ls) :- 
    setof((W,Z), Stations1^Stations2^(
    route(W, Stations1), 
    route(Z, Stations2), 
    disjoint(Stations1, Stations2) 
), Ls). 

disjoint(Stations1, Stations2) :- 
    ... % could be easy as intersection(Stations1, Stations2, []) 
     % or something more efficient: early fail at first shared 'station' 
+0

Merci beaucoup! J'ai ajouté la définition suivante pour résoudre le problème suite à votre suggestion: notMembers ([], _). notMembers ([H | T], L): - notMembers (T, L), non membre (H, L). La solution complète me donne des doublons de [(X, Y), (Y, X)] donc la suppression de ces doublons serait la dernière étape pour moi :) – qwerty

+0

Pour supprimer les doublons, vous pouvez utiliser 'W @

1

setof/3 est plus facile à utiliser si vous créez un prédicat auxiliaire qui exprime la relation que vous êtes intéressé par:

disjoint_routes(W, Z) :- 
    route(W, Stations1), 
    route(Z, Stations2), 
    disjoint(Stations1, Stations2). 

avec cela, la définition de disjointed_lines/1 devient plus court et plus simple et n'a plus besoin de ^ opérateurs:

disjointed_lines(Ls) :- 
    setof((W, Z), disjoint_routes(W, Z), Ls). 

Les variables dont vous ne voulez pas dans le résultat de setof/3 sont automatiquement masquées dans la définition de prédicat auxiliaire.

+0

Merci beaucoup, c'est un bon conseil! Je vais certainement l'utiliser si j'avais plus de problèmes avec^:) – qwerty