2016-09-23 2 views
0

Мне было интересно, есть ли способ в DLV для создания списка с элементами всех предикатов, которые истинны в правиле. Например, если у меня есть следующие предикатыСостав списка DLV

foo(a, b). 
foo(a, c). 
foo(a, e). 
foo(b, c). 

В результате я ищу должен быть новыми предикатами, где первый элемент является первым параметром foo и второй параметр должен содержать список всех элементов, связанных с первый параметр. Эмпирически:

bar(a, [b,c,e]). 
bar(b, [c]). 

Я знаю, что есть способ получения этих результатов (плюс много больше) со следующим кодом:

bar(A, [X]) :- foo(A, X). 
bar(A, P) :- bar(A, P0), 
       foo(A, X), 
       not #member(X, P0), 
       #insLast(P0, X, P). 

Но я хотел бы знать, если есть способ предотвращения генерирование всех возможных списков размером от 1 до N (являющееся N числом элементов окончательного списка). Я хотел бы сделать это по двум причинам: (1) уменьшить вычислительные затраты (2) предотвратить отказ от всех ненужных предикатов.

Если расчетная стоимость не является проблемой, которая может быть, я имел в виду следующие изменения для того, чтобы сохранить только предикаты с крупнейшими списками:

tmp_bar(A, [X], 1) :- foo(A, X). 
tmp_bar(A, P, L) :- tmp_bar(A, P0, L0), 
         foo(A, X), 
         not #member(X, P0), 
         #insLast(P0, X, P), 
         L = L0 + 1. 
bar(A, P)  :- tmp_bar(A, P, L), 
        max_list(A, L). 
max_list(A, L) :- foo(A, _), 
        #max{X: tmp_bar(A, P, X)} = L. 

Однако, это начинает усложняется и отображает все списки максимального размера, а не только один из них. Как мне избавиться от всех, кроме одного? Я попробовал создать бар (A, P) только в том случае, если их нет другого бара (A, _), но я получаю «правило небезопасно». Также попытался подсчитать количество вхождений и подобных проблем ...

Самое главное, можно ли получить результаты, которые я ожидаю сразу, без этих трюков?

Любая помощь с учётом,

Thanks!

ответ

0

По-видимому, я нашел решение проблемы, добавив элементы в определенном порядке. Я делаю это, чтобы добавить элемент в конец списка, только если он меньше последнего элемента текущего списка. Я имел дело с именами, а не с цифрами, поэтому, хотя это было невозможно).

Вот код:

tmp_bar(A, [X], 1) :- foo(A, X). 
tmp_bar(A, P, L) :- tmp_bar(A, P0, L0), 
         foo(A, X), 
         #last(P0, Y), 
         Y < X, 
         #insLast(P0, X, P), 
         L = L0 + 1. 

bar(A, P) :- tmp_bar(A, P, L), 
      max_list(A, L). 

max_list(A, L) :- foo(A, _), 
       #max{X: tmp_bar(A, P, X)} = L. 

Надеется, что это помогает кто-то еще в будущем.

Смежные вопросы