Search code examples
if-statementprologinstantiation-error

prolog arguments are not sufficently instantiated


I am trying to find max,mid and min number from 3 given number. The code is:

t_max(X,Y,Z):-
    A is max(max(X,Y),max(Y,Z)),
    C is min(min(X,Y),min(Y,Z)),
    (X>=A,X=<C)->B is X;
    (Y>=A,Y=<C)->B is Y;
    (Z>=A,Z=<C)->B is Z;
    format('~w      ~w      ~w',[A,B,C]).

When i try to run the method with any three numbers, I get this error

ERROR: >=/2: Arguments are not sufficiently instantiated

Why I'm getting this error?


Solution

  • The problem is that the ; binds with lower priority than the , so what you have written is equivalent to:

    t_max(X, Y, Z) :-
        (   A is max(max(X, Y), max(Y, Z)),
            C is min(min(X, Y), min(Y, Z)),
            X>=A,
            X=<C
        ->  B is X
        ;   Y>=A,
            Y=<C
        ->  B is Y
        ;   Z>=A,
            Z=<C
        ->  B is Z
        ;   format('~w      ~w      ~w', [A, B, C])
        ).
    

    What does this mean: Prolog evaluates:

    A is max(max(X,Y),max(Y,Z)),
    C is min(min(X,Y),min(Y,Z)),
    

    first and then checks the condition:

    X>=A,X=<C
    

    if that fails however, the program backtracks entirely to the beginning of the clause. So now A and C are again uninstantiated and Prolog performs a new attempt by checking:

    Y>=A,Y=<C
    

    but now A and C are not grounded.

    You can resolve the problem by adding brackets:

    t_max(X,Y,Z):-
        A is max(max(X,Y),max(Y,Z)),
        C is min(min(X,Y),min(Y,Z)),
        ((X>=C,X=<A)
         -> B is X
         ; ((Y>=C,Y=<A)
            ->B is Y
            ; ((Z>=C,Z=<A)
               -> B is Z;
               true
              )
           )
        ),
        format('~w      ~w      ~w',[A,B,C]).
    

    If I understand your problem correctly. If you however want to sort them from large to small, a compact way to do this for three numbers is:

    t_max(X,Y,Z) :-
        Max is max(X,max(Y,Z)),
        Min is min(X,min(Y,Z)),
        Mid is X+Y+Z-Max-Min,
        format('~w      ~w      ~w',[Max,Mid,Min]).