уникальные результаты пролога - PullRequest
5 голосов
/ 07 апреля 2009

Есть ли простой способ сделать запрос в прологе, возвращающий каждый результат только один раз?

например, я пытаюсь что-то вроде:

deadly(Xn) :- scary(X), Xn is X - 1, Xp is X + 1, not(safe(Xn)), safe(Xp).
deadly(Xp) :- scary(X), Xn is X - 1, Xp is X + 1, not(safe(Xp)), safe(Xn).

deadly(X).

и получение

X = 5

X = 5

X = 5

X = 5

....

Не для меня.

Ответы [ 4 ]

4 голосов
/ 07 апреля 2009

Одна вещь, которую вы можете сделать, это применить setof/3 к предикату, который генерирует решения. Но обратите внимание, что setof/3 реализуется путем применения sort/2 к результату, полученному с помощью bagof/3 (по крайней мере, это имеет место в SWI-Prolog). Таким образом, если ваш генератор решений работает вечно, то setof/3 никогда не будет применен ...

Так что я бы сказал, что попытайтесь запрограммировать так, чтобы дубликаты не генерировались, т. Е. Используя вырез (!) Там, где это имеет смысл.

3 голосов
/ 07 апреля 2009

Другой подход - запоминать решения.

:- dynamic seen/1.

% Call this always before calling deadly_wrapper/1
clear_seen :-
    retractall(seen(_)).

% This wrapper calls deadly/1 but remembers
% the solution using assert/1, and fails
% if the solution has been "seen" before.
deadly_wrapper(X) :-
    deadly(X),
    (
        seen(X)
    ->  
        fail
    ;
        assert(seen(X))
    ).  


% This is for testing.
deadly(1).
deadly(1).
deadly(1).
deadly(5).
deadly(1).
deadly(1).

Если ваш Prolog поддерживает табулирование, это становится еще проще. Файл примера:

:- table deadly/1.

deadly(1).
deadly(1).
deadly(5).
deadly(1).
deadly(5).

Пример выполнения с XSB :

$ xsb
[xsb_configuration loaded]
[sysinitrc loaded]

XSB Version 3.2 (Kopi Lewak) of March 15, 2009
[x86_64-unknown-linux-gnu; mode: optimal; engine: slg-wam;
 scheduling: local; word size: 64]

| ?- [deadly_tab].
[Compiling ./deadly_tab]
[deadly_tab compiled, cpu time used: 0.0100 seconds]
[deadly_tab loaded]

yes
| ?- deadly(X).

X = 5;

X = 1;

no
| ?- 
3 голосов
/ 07 апреля 2009

Если я правильно помню, существует предикатное решение (или подобное, я давно программировал на Прологе), которое собирает уникальные решения в списке.

Редактировать: setof/3 это тот, о котором я думал. Спасибо, Каарел.

1 голос
/ 07 апреля 2009

Сложно сказать без кода, но вы, вероятно, ищете оператор разрезания (!). Если вы хотите опубликовать определение из foo, я (или кто-то еще, кто следует) может дать подробный / конкретный ответ.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...