2017-01-01 2 views
0

J'ai des données déclarées dans un fichier Prolog qui ressemble à ce qui suit:Prolog assurer que les paramètres de retour d'une règle sont uniques et ordre canonique

gen1(grass). 
gen1(poison). 
gen1(psychic). 
gen1(bug). 
gen1(rock). 

...

gen1((poison, flying)). 
gen1((ghost, poison)). 
gen1((water, ice)). 

...

weak1(grass, poison). 
weak1(grass, bug). 
weak1(poison, rock). 

strong1(grass, rock). 
strong1(poison, grass). 
strong1(bug, grass). 
strong1(poison, bug). 
strong1(psychic, poison). 
strong1(bug, poison). 
strong1(bug, psychic). 
strong1(rock, bug). 

Notez que les données ne définit pas strong1 ou weak1 pour compou sd gen1(...). Ceux-ci sont déterminés par des règles qui ne contribuent pas à l'exemple de travail minimal. Je les mentionne parce qu'il pourrait être utile de savoir qu'ils existent. J'essaie de trouver des relations entre ces termes qui forment un cycle. Voici une fonction exemple:

triangle1(A, B, C) :- 
    setof(A-B-C, (
      gen1(A), gen1(B), gen1(C), A \= B, A \= C, B \= C, 
       strong1(A, B), strong1(B, C), strong1(C, A) 
      ), Tris), 
    member(A-B-C, Tris). 

Cette configuration ne supprime les doublons où A, B et C sont dans le même ordre. Cependant, il ne supprime pas les doublons dans les différentes commandes. Par exemple:

?- triangle1(A, B, C), 
    member(A, [bug, grass, rock]), 
    member(B, [bug, rock, grass]), 
    member(C, [bug, rock, grass]). 
A = bug, 
B = grass, 
C = rock ; 
A = grass, 
B = rock, 
C = bug ; 
A = rock, 
B = bug, 
C = grass ; 
false. 

Cette requête ne doit retourner un ensemble de [A, B, C].

J'ai pensé à utiliser sort/2, mais il y a des cas où tout simplement de tri change le sens de la réponse:

?- triangle1(A, B, C), 
    sort([A, B, C], [D, E, F]), 
    \+member([D, E, F], [[A, B, C], [B, C, A], [C, A, B]]). 
A = D, D = bug, 
B = F, F = psychic, 
C = E, E = poison . 

J'ai aussi essayé < et >, mais ceux qui ne fonctionnent pas sur les atomes, apparemment .

Des pensées?

(je regardais les questions similaires, mais ne sais pas comment ce que je fais ici se compare à ce que les autres font)

EDIT: Comme par exemple commentaires sur un minimum de travail.

+0

Vous devez lire [demander], puis nous donner un [mcve]. – Enigmativity

+0

@Enigmativity J'ai déjà lu cela auparavant, et j'ai essayé de le respecter ici.Je reconnais que la question pourrait être légèrement plus ciblée, et les données de l'échantillon ne sont pas les plus pertinentes pour le contenu de la question. Je vais éditer la question avec de meilleures données d'échantillon, et cela devrait fournir l'exemple minimal, bien que dans le style de programmation alphabète. – proegssilb

Répondre

2

Vous pouvez essayer de trier à l'intérieur l'appel setof/3. Donc, vous devriez éviter la génération de triplets dans le mauvais ordre.

Je veux dire: appeler setof/3, au lieu de

A \= B, A \= C, B \= C, 

essayez avec

A @< B, A @< C, B \= C, 

De cette façon, vous imposez que A est inférieur à B et inférieur à C, vous éviter les doublons et de maintenir des solutions correctes .

Le triangle1/3 complet

triangle1(A, B, C) :- 
    setof(A-B-C, (
      gen1(A), gen1(B), gen1(C), A @< B, A @< C, B \= C, 
       strong1(A, B), strong1(B, C), strong1(C, A) 
      ), Tris), 
    member(A-B-C, Tris). 
+0

L'utilisation de 'setof/3' supprime les doublons dus aux chemins multiples d'un atome à l'autre. Ceci est basé sur https://stackoverflow.com/questions/16243081/how-can-i-prevent-duplicates-in-prolog, et est particulièrement pratique pour les types composés. Vous aurez besoin du code complet pour comprendre: https://gist.github.com/proegssilb/4bbc307ffad40e0ee337edc55dc2c4e6 – proegssilb

+0

@proegssilb - J'ai essayé votre code complet (réorganiser les clauses ou mon gprolog en ignore beaucoup) avec un triangle1/3' basé sur 'setof/3' et avec ma version semplifiée' triangle1/3'; En appelant 'triangle (A, B, C)' j'obtiens, dans les deux cas, 854 résultats qui sont exactement les mêmes (et dans le même ordre). – max66

+0

Oh, j'utilise SWI Prolog 6.2.6, pas GNU Prolog. Dans SWI Prolog, les règles pour 'strong/2' et' weak/2' génèrent des résultats doubles pour des cas comme 'strong (X, (dragon, flying))', parce que 'strong '(ice, dragon)' et 'strong (ice, flying) 'sont définis (Au moins, c'est ce que je comprends du GUI Tracer, même pas à distance, comment fonctionne Prolog). – proegssilb