Search code examples
loopsprologdeclarativefailure-slicedeclarative-programming

Prolog loop after results


So I wrote this predicate to find all possible subsets + permutations of a list. I get the correct output but for some reason the program keeps looping after giving me all the (correct) results.

What am I doing wrong?

% Gets all subsets of a list
aSubset([], []).
aSubset([E|Tail], [E|NTail]):- aSubset(Tail, NTail).
aSubset([_|Tail], NTail):- aSubset(Tail, NTail).

% gets all subsets and permutates them
allSubsets([],[]).
allSubsets(X, Res) :- permutation(S, Res), aSubset(X, S).

the results that I get for allSubsets([1,2,3], X) are:

4 ?- allSubsets([1,2,3], X).
X = [] ;
X = [1] ;
X = [2] ;
X = [3] ;
X = [1,2] ;
X = [1,3] ;
X = [2,3] ;
X = [2,1] ;
X = [3,1] ;
X = [3,2] ;
X = [1,2,3] ;
X = [1,3,2] ;
X = [2,1,3] ;
X = [2,3,1] ;
X = [3,1,2] ;
X = [3,2,1] ;
Action (h for help) ? abort
% Execution Aborted

where I have to abort the loop in the last two lines.

Thanks in advance.


Solution

  • Not only allSubset([1,2,3], X) loops, but also the much shorter allSubset([], X).

    The following program fragment (failure-slice) loops already. So no need to look any further.

    allSubsets([],[]) :- false.
    allSubsets(X, Res) :-
       permutation(S, Res), false,
       aSubset(X, S).
    

    To improve this, you need to change something in the visible part. Currently, only Arg2 (Res) can influence the goal permutation(S, Res), Arg1 (X) occurs only in the second goal, when it is already too late to influence (universal) termination of the first.