next up previous
Next: Question 3 Up: No Title Previous: Question 1

Question 2

We can implement a setof predicate in Prolog by using the database capabilities of the language (i.e., assert and retract).

The solution involves collecting in the database all the solutions of the goal, generated through a fail-driven recursion, collecting the solutions in a list, and removing eventual repetitions.

This is sketched in the following code:

%% Assumption: '$sol' and '$count' are reserved predicates 

:- dynamic '$sol'/2.
:- dynamic '$count'/1.

my_setof(X,Goal,List) :-
      assert('$count'(1)),
      fail_loop(X,Goal),
      collect_facts([],List1),!,
      remove_repetitions(List1,List).

% Main Loop: generate solution, assert it (tagged with 
%            a time stamp, and fail for the next one

fail_loop(X,Goal) :-
      Goal,
      get_count(N),
      assert('$sol'(N,X)),
      fail.
fail_loop(_,_).

% Increments deterministically the counter

get_count(N) :-
     '$count'(N),
     retract('$count'(N)),
     N1 is N+1,
     assert('$count'(N1)),!.

% extract all the '$sol' facts from the database

collect_facts(LIn,LOut) :-
      '$sol'(N,X),
      retract('$sol'(N,X)),
      collect_facts([X|LIn],LOut).
collect_facts(L,L).

remove_repetitions([],[]).
remove_repetitions([A|B],L) :-
      eq_member(A,B),!,
      remove_repetitions(B,L).
remove_repetitions([A|B],[A|L]) :-
      remove_repetitions(B,L).

eq_member(X,[Y|_]) :-
      X == Y.
eq_member(X,[_|Y]) :-
      eq_member(X,Y).



Chito
1999-07-06