concurrencyprologswi-prologmeta-predicate

Meta-predicate that receives a list of goals as input


I've implemented the following meta-predicate that use SWI-Prolog engines to simultaneously enumerate solutions to two or more backtrackable predicates.

enumerate(Gs) :-
   maplist(term_variables, Gs, Xs),
   findall(E,
           ( nth1(I, Gs, G),
             nth1(I, Xs, X),
             engine_create(X, G, E) ),
           Es),
   enumerate_next(Es, Xs).

enumerate_next(Es, Xs) :-
   repeat,
   (   findall(X,
               ( member(E, Es),
                 engine_next(E, X) ),
               Xs)
   ->  true
   ;   !,
       fail ).

Example of use:

?- enumerate([between(1,inf,X), member(Y,[a,b,c,d,e]), append(Z,W,[1,2,3,4])]).
X = 1,
Y = a,
Z = [],
W = [1, 2, 3, 4] ;

X = 2,
Y = b,
Z = [1],
W = [2, 3, 4] ;

X = 3,
Y = c,
Z = [1, 2],
W = [3, 4] ;

X = 4,
Y = d,
Z = [1, 2, 3],
W = [4] ;

X = 5,
Y = e,
Z = [1, 2, 3, 4],
W = [] ;
false.

My question is: how should I declare this meta-predicate?


Solution

  • I think it should be

    :- meta_predicate enumerate(:).
    

    but then you should handle in some way goals list' elements: for instance

    :- module(enumerate,
              [enumerate/1]).
    
    :- meta_predicate enumerate(:).
    
    enumerate(GsDecl) :-
       strip_module(GsDecl,GsM,Gs),
       maplist(term_variables, Gs, Xs),
       findall(E,
               ( nth1(I, Gs, G),
                 nth1(I, Xs, X),
                 engine_create(X, GsM:G, E) ),
               Es),
       enumerate_next(Es, Xs).
    
    ...