0

我想知道 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.

但是,这开始变得复杂,并显示所有最大大小的列表,而不仅仅是其中一个。我如何摆脱除一个之外的所有?我尝试生成 bar(A,P) 只有在它们不是其他 bar(A, _) 但我得到“规则不安全”的情况下。还尝试计算出现次数和出现类似问题...

最重要的是,是否有可能在没有那么多技巧的情况下一次获得我期望的结果?

任何帮助表示赞赏,

谢谢!

4

1 回答 1

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.

希望它在未来对其他人有所帮助。

于 2016-09-23T10:15:11.893 回答