Search code examples
prologclpfdinstantiation-error

Trying to generate list of non-zero integers in Prolog


I'm trying to define the function int(?X) in prolog which is a non-zero integer number generator which works like this:

?- int(X). X = 1 ; X = -1 ; X = 2 ; X = -2 ;

I tried the following with no luck:

int(X):- positives(Y), Y is abs(X).

positives(1).
positives(X):- positives(Y), X is Y+1.

but I'm getting the following error:

ERROR: is/2: Arguments are not sufficiently instantiated

How can I make this work? Thanks!


Solution

  • There is an easy way to find and correct such problems.

    1. Step one: Put constraints in your program. To do this, simply1 replace (is)/2 by the CLP(FD) constraint (#=)/2, i.e.:

      int(X) :- positives(Y), Y #= abs(X).
      
      positives(1).
      positives(X):- positives(Y), X #= Y+1.
      
    2. Step two: The query now completes without errors, and shows you what you are describing:

      ?- int(X).
      X in -1\/1 ;
      X in -2\/2 ;
      X in -3\/3 ;
      X in -4\/4 .
      

      So, from the above, you see that what you are describing is not sufficient to obtain ground solutions: There is still a certain degree of freedom in your relations.

    3. Step three: To actually fix the problem, we think about what we actually want to describe. Here is a start:

      int(X) :- positives(Y), ( X #= Y ; X #= -Y).
      
    4. Step four: We try it out:

      ?- int(X).
      X = 1 ;
      X = -1 ;
      X = 2 ;
      X = -2 ;
      X = 3 ;
      etc.
      

    Seems to work OK, except for the fact that natural numbers are actually never negative. I leave fixing this discrepancy between the title of your question and the relation you are describing as an exercise for you.

    TL;DR: When reasoning over integers, use your system's CLP(FD) constraints, then take it from there.


    I am assuming that you have already put :- use_module(library(clpfd)). somewhere in your initial file, so that you can use CLP(FD) constraints in all your programs.