Мне было интересно, есть ли способ в 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!