Search code examples
listprolog

Prolog print all possible Lists


I am trying to print out every possible list for a given variable. With native functions, this is working fine, but as soon as I do this with lists, prolog throws an exception.

This is my code (simplified):

first(A, L) :- L = [K|_], A = K.                % First element of L is A
second(A, L) :- L = [_|R], R=[F|_], A = F.      % Second element of L is A
third(A, L) :- L = [_|R], second(A, R).         % Third element of L is A

konst(S) :- first(X, S), second(Y,S), third(Z,S), X >= 0, Y >= 0, Z >= 0, X =< 3, Y =< 4, Z =< 5.

| ?- konst(S).
uncaught exception: error(instantiation_error,(>=)/2)

So basically it should print out every single list between [0,0,0] and [3,4,5].

Am I missing something here?


Solution

  • Your definition just speaks about lists but does not define that the values are numbers. In particular, the arithmetic predicates like =< can only compare concrete numbers: 1 =< 2 succeeds but X =< 2 leads to the instantiation error you found.

    To solve your problem you can use the predicate between/3 that succeeds if the range given by the first two arguments covers the third:

    p([A,B,C]) :-
      between(0, 3, A),
      between(0, 4, B),
      between(0, 5, C).
    

    Then the query

    ?- p([A,B,C]), A < 1, B < 1, C < 1.
    A = B, B = C, C = 0 ;
    false.
    

    works as expected. This is due to the limitations of Prolog's built-in arithmetic. If you want to go beyond that the keyword is (finite) constraint logic programming (CLP). One of the Prolog libraries for that is clp(Z).