Пролог гарантирует, что возвращаемые параметры правила уникальны и находятся в каноническом порядке.

У меня есть некоторые данные, объявленные в файле Prolog, которые выглядят следующим образом:

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).

Обратите внимание, что данные не определяют strong1 или weak1 для соединения gen1(...). Они определяются правилами, которые не способствуют минимальному рабочему примеру. Я упоминаю их, потому что может быть полезно знать, что они существуют.

Я пытаюсь найти отношения между этими терминами, образующими цикл. Вот один пример функции:

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).

Эта настройка удаляет дубликаты, где A, B и C находятся в одном и том же порядке. Однако он не удаляет дубликаты в разных порядках. Например:

?- 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.

Этот запрос должен возвращать только один набор [A, B, C].

Я думал об использовании sort/2, но бывают случаи, когда простая сортировка меняет смысл ответа:

?- 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 .

Я также пробовал < и >, но они, по-видимому, не работают с атомами.

Есть предположения?

(Я просмотрел похожие вопросы, но понятия не имею, как то, что я здесь делаю, сравнивается с тем, что делают другие люди)

РЕДАКТИРОВАТЬ: Согласно комментарию о минимальном рабочем примере.


person xenrelay    schedule 01.01.2017    source источник
comment
Вам нужно прочитать Как спросить, а затем предоставить нам минимально воспроизводимый пример.   -  person Enigmativity    schedule 01.01.2017
comment
@Enigmativity Я действительно читал это раньше и пытался соответствовать этому здесь. Я признаю, что вопрос мог бы быть немного более сфокусированным, и данные выборки не являются наиболее соответствующими содержанию вопроса. Я отредактирую вопрос с лучшими примерами данных, и это должно предоставить минимальный пример, хотя и в стиле грамотного программирования.   -  person xenrelay    schedule 01.01.2017


Ответы (1)


Вы можете попробовать отсортировать внутри вызова setof/3. Поэтому вам следует избегать генерации троек в неправильном порядке.

Я имею в виду: вызов setof/3 вместо

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

попробуй с

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

Таким образом, вы устанавливаете, что A ниже, чем B, и ниже, чем C, вы избегаете дублирования и поддерживаете правильные решения.

Полный triangle1/3

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).
person max66    schedule 01.01.2017
comment
Использование setof/3 удаляет дубликаты из-за множественных путей от одного атома к другому. Это основано на stackoverflow.com /questions/16243081/ и особенно удобен для составных типов. Чтобы понять, вам понадобится полный код: gist.github.com/proegssilb/4bbc307ffad40e0ee337edc55dc2c4e6 - person xenrelay; 01.01.2017
comment
@proegssilb - я пробовал ваш полный код (переупорядочивание предложений или мой gprolog игнорирует многие из них) с triangle1/3 на основе setof/3 и с моей упрощенной версией triangle1/3; вызывая triangle(A, B, C), я получаю в обоих случаях 854 результата, которые абсолютно одинаковы (и в том же порядке). - person max66; 01.01.2017
comment
О, я использую SWI Prolog 6.2.6, а не GNU Prolog. В SWI Prolog правила для strong/2 и weak/2 генерируют двойные результаты для таких случаев, как strong(X, (dragon, flying)), потому что определены и strong(ice, dragon), и strong(ice, flying) (по крайней мере, это то, что я понимаю из GUI Tracer; я даже отдаленно не разбираюсь в том, как работает Prolog). - person xenrelay; 01.01.2017
comment
@proegssilb - извините: вы правы: правила strong1(A, (B, C)) и подобные вводят дублированное решение. Хорошо с bagof/3. - person max66; 01.01.2017