问题
I was wondering if there is a way in DLV for creating a list with the elements of all predicates that are true in a rule. For example, if I have the following predicates
foo(a, b).
foo(a, c).
foo(a, e).
foo(b, c).
The result I am looking for should be new predicates where the first element is the first parameter of foo
and the second parameter should contain a list with all the elements associated to the first parameter. Empirically:
bar(a, [b,c,e]).
bar(b, [c]).
I know there is a way of getting these results (plus many more) with the following code:
bar(A, [X]) :- foo(A, X).
bar(A, P ) :- bar(A, P0),
foo(A, X),
not #member(X, P0),
#insLast(P0, X, P).
But I would like to know if there is a way of preventing the generation of all possible lists of size from 1 to N (being N the number of elements of the final list). I would like to do it for two reasons: (1) reduce computational cost (2) prevent discarding all unnecessary predicates.
If the computational cost was not a problem, which may be the case, I was thinking of the following changes in order to keep only the predicates with the largest lists:
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.
However, this starts to get complicated and is showing all of the lists of maximum size and not only one of them. How do I get rid of all but one? I tried generating bar(A,P) only in case their is no other bar(A, _) but I get "rule is not safe". Also tried counting the number of occurrences and similar problems appear...
Most importantly, is it possible to get the results I expect all at once without that many tricks?
Any help is appreciated,
Thanks!
回答1:
Apparently I found a solution to the problem by adding elements in a particular order. What I do is to add the element at the end of the list only if its smaller than the last element of the current list. I was dealing with names rather than numbers so I though this wasn't possible).
Here is the code:
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.
Hope it helps someone else in the future.
来源:https://stackoverflow.com/questions/39655922/dlv-list-composition