prologinstantiation-error

Arguments are not sufficiently instantiated prolog


Trying to write a program that solves this problem:

"You are given two jugs, a 5-gallon one and a 3-gallon one. Neither of them has any measuring markers on it. There is a tap that can be used to fill the jugs with water. The goal is to obtain exactly 4 gallons of water." This is the code I currently have:

%(WaterInThree, WaterInFive)
s(A,B).

initial(s(0,0)).

goal(s(A,B)):- A + B =:= 4.

valid(A,B) :- A =< 3, A >=0, B =< 5, B >= 0.

changeState(s(0,B),s(3,B)).
changeState(s(A,0),s(A,5)).
changeState(s(A,B),s(A,0)) :- B > 0, valid(A,B).
changeState(s(A,B),s(0,B)) :- A > 0, valid(A,B).
changeState(s(A,B),s(C,D)) :- B =< 2, D is A + B, C is B - A, valid(C,D).
changeState(s(A,B),s(C,D)) :- B > 2, D is B + ( (5 - A) mod 5), valid(C,D).
changeState(s(A,B),s(3,D)) :- B =< 3, D is B - (3 - A), valid(A,D).
changeState(s(A,B),s(C,D)) :- B =:= 5, C is A + B, D is A - B, valid(C,D).


traverse(StartNode,Sol,_) :- goal(StartNode), Sol = [StartNode].
traverse(StartNode,Sol,Visit) :- changeState(StartNode, NextNode),
   not(member(NextNode, Visit)),
   traverse(NextNode, PartialSol, [NextNode|Visit]),
   Sol = [StartNode | PartialSol].

When I execute this code, I get these errors:

ERROR: Arguments are not sufficiently instantiated
ERROR: In:
ERROR:   [13] _11226=<3
ERROR:   [12] valid(_11252,5+(5-3)) 
ERROR:   [11] changeState(s(3,5),s(_11302,5+ ...)) 
ERROR:   [10] traverse(s(3,5),_11336,[s(3,5),...|...]) 
ERROR:    [9] traverse(s(3,0),_11388,[s(3,0),...]) 
ERROR:    [8] traverse(s(0,0),_11440,[s(0,0)]) 
ERROR:    [7] <user>

Not really sure what the issue is, I've been trying to fix this for hours on end and can't figure out what's wrong. Can't even properly test if the changeState predicates I've created even work because of this so it's extremely frustrating. Would appreciate any help!

EDIT I've narrowed it down to the this line causing the error:

changeState(s(A,B),s(C,D)) :- B > 2, D is B + ( (5 - A) mod 5), valid(C,D).

Can't really see how this would cause that error though.


Solution

  • Can't really see how this

    changeState(s(A,B),s(C,D)) :- B > 2, D is B + ( (5 - A) mod 5), valid(C,D).
    

    would cause that error though.

    _10148=<3
    ERROR: Arguments are not sufficiently instantiated
    

    For

    changeState(s(A,B),s(C,D)) :- 
      B > 2, 
      D is B + ( (5 - A) mod 5), 
      valid(C,D).
    

    when this is executed (called) the query is

    changeState(s(0, 5), X)
    
    A is bound to 0
    B is bound to 5
    X is bound to s(C,D)
    

    then for

    B > 2
    

    the query is

    5 > 2
    

    which is true

    then for

    D is B + ( (5 - A) mod 5)
    

    the query is

    D is 5 + ( (5 - 0) mod 5)
    
    D is bound to 5
    

    then for

    valid(C,D)
    
    C is unbound
    D is bound to 5
    

    the query is

    valid (<unbound>,5)
    

    the only predicate to match is

    valid(A,B) :- A =< 3, A >=0, B =< 5, B >= 0.
    
    A is unbound
    B is bound to 5
    

    then for

    A =< 3
    

    since A is unbound the comparison =< gives the error because it needs both variables to be bound.

    So back at this statement

    changeState(s(A,B),s(C,D)) :- B > 2, D is B + ( (5 - A) mod 5), valid(C,D).
    

    you need to bind C to a value.


    If you use set up the trace with

    ?- visible(+all),leash(-all).
    

    then enable tracing

    ?- trace.
    

    and run your query you get

    ?- traverse(s(0,0), Sol, [s(0,0)]).
       Call: (8) traverse(s(0, 0), _9866, [s(0, 0)])
       Unify: (8) traverse(s(0, 0), _9866, [s(0, 0)])
       Call: (9) goal(s(0, 0))
       Unify: (9) goal(s(0, 0))
       Call: (10) 0+0=:=4
       Fail: (10) 0+0=:=4
       Fail: (9) goal(s(0, 0))   
       Redo: (8) traverse(s(0, 0), _9866, [s(0, 0)])
       Unify: (8) traverse(s(0, 0), _9866, [s(0, 0)])
       Call: (9) changeState(s(0, 0), _10092)
       Unify: (9) changeState(s(0, 0), s(3, 0))
       Exit: (9) changeState(s(0, 0), s(3, 0))
    ^  Call: (9) not(member(s(3, 0), [s(0, 0)]))
    ^  Unify: (9) not(user:member(s(3, 0), [s(0, 0)]))
    ^  Exit: (9) not(user:member(s(3, 0), [s(0, 0)]))
       Call: (9) traverse(s(3, 0), _10116, [s(3, 0), s(0, 0)])
       Unify: (9) traverse(s(3, 0), _10116, [s(3, 0), s(0, 0)])
       Call: (10) goal(s(3, 0))
       Unify: (10) goal(s(3, 0))
       Call: (11) 3+0=:=4
       Fail: (11) 3+0=:=4
       Fail: (10) goal(s(3, 0))   
       Redo: (9) traverse(s(3, 0), _10116, [s(3, 0), s(0, 0)])
       Unify: (9) traverse(s(3, 0), _10116, [s(3, 0), s(0, 0)])
       Call: (10) changeState(s(3, 0), _10116)
       Unify: (10) changeState(s(3, 0), s(3, 5))
       Exit: (10) changeState(s(3, 0), s(3, 5))   
    ^  Call: (10) not(member(s(3, 5), [s(3, 0), s(0, 0)]))
    ^  Unify: (10) not(user:member(s(3, 5), [s(3, 0), s(0, 0)]))
    ^  Exit: (10) not(user:member(s(3, 5), [s(3, 0), s(0, 0)]))
       Call: (10) traverse(s(3, 5), _10140, [s(3, 5), s(3, 0), s(0, 0)])
       Unify: (10) traverse(s(3, 5), _10140, [s(3, 5), s(3, 0), s(0, 0)])
       Call: (11) goal(s(3, 5))
       Unify: (11) goal(s(3, 5))
       Call: (12) 3+5=:=4
       Fail: (12) 3+5=:=4
       Fail: (11) goal(s(3, 5))   
       Redo: (10) traverse(s(3, 5), _10140, [s(3, 5), s(3, 0), s(0, 0)])
       Unify: (10) traverse(s(3, 5), _10140, [s(3, 5), s(3, 0), s(0, 0)])
       Call: (11) changeState(s(3, 5), _10140)
       Unify: (11) changeState(s(3, 5), s(3, 0))
       Call: (12) 5>0
       Exit: (12) 5>0
       Call: (12) valid(3, 5)
       Unify: (12) valid(3, 5)
       Call: (13) 3=<3
       Exit: (13) 3=<3
       Call: (13) 3>=0
       Exit: (13) 3>=0
       Call: (13) 5=<5
       Exit: (13) 5=<5
       Call: (13) 5>=0
       Exit: (13) 5>=0
       Exit: (12) valid(3, 5)   
       Exit: (11) changeState(s(3, 5), s(3, 0))
    ^  Call: (11) not(member(s(3, 0), [s(3, 5), s(3, 0), s(0, 0)]))
    ^  Unify: (11) not(user:member(s(3, 0), [s(3, 5), s(3, 0), s(0, 0)]))
    ^  Fail: (11) not(user:member(s(3, 0), [s(3, 5), s(3, 0), s(0, 0)]))
       Redo: (11) changeState(s(3, 5), _10140)
       Unify: (11) changeState(s(3, 5), s(0, 5))
       Call: (12) 3>0
       Exit: (12) 3>0
       Call: (12) valid(3, 5)
       Unify: (12) valid(3, 5)
       Call: (13) 3=<3
       Exit: (13) 3=<3
       Call: (13) 3>=0
       Exit: (13) 3>=0
       Call: (13) 5=<5
       Exit: (13) 5=<5
       Call: (13) 5>=0
       Exit: (13) 5>=0
       Exit: (12) valid(3, 5)
       Exit: (11) changeState(s(3, 5), s(0, 5))
    ^  Call: (11) not(member(s(0, 5), [s(3, 5), s(3, 0), s(0, 0)]))
    ^  Unify: (11) not(user:member(s(0, 5), [s(3, 5), s(3, 0), s(0, 0)]))
    ^  Exit: (11) not(user:member(s(0, 5), [s(3, 5), s(3, 0), s(0, 0)]))
       Call: (11) traverse(s(0, 5), _10164, [s(0, 5), s(3, 5), s(3, 0), s(0, 0)])
       Unify: (11) traverse(s(0, 5), _10164, [s(0, 5), s(3, 5), s(3, 0), s(0, 0)])
       Call: (12) goal(s(0, 5))
       Unify: (12) goal(s(0, 5))
       Call: (13) 0+5=:=4
       Fail: (13) 0+5=:=4
       Fail: (12) goal(s(0, 5))   
       Redo: (11) traverse(s(0, 5), _10164, [s(0, 5), s(3, 5), s(3, 0), s(0, 0)])
       Unify: (11) traverse(s(0, 5), _10164, [s(0, 5), s(3, 5), s(3, 0), s(0, 0)])
       Call: (12) changeState(s(0, 5), _10164)
       Unify: (12) changeState(s(0, 5), s(3, 5))
       Exit: (12) changeState(s(0, 5), s(3, 5))
    ^  Call: (12) not(member(s(3, 5), [s(0, 5), s(3, 5), s(3, 0), s(0, 0)]))
    ^  Unify: (12) not(user:member(s(3, 5), [s(0, 5), s(3, 5), s(3, 0), s(0, 0)]))
    ^  Fail: (12) not(user:member(s(3, 5), [s(0, 5), s(3, 5), s(3, 0), s(0, 0)]))
       Redo: (12) changeState(s(0, 5), _10164)
       Unify: (12) changeState(s(0, 5), s(0, 0))
       Call: (13) 5>0
       Exit: (13) 5>0
       Call: (13) valid(0, 5)
       Unify: (13) valid(0, 5)
       Call: (14) 0=<3
       Exit: (14) 0=<3
       Call: (14) 0>=0
       Exit: (14) 0>=0
       Call: (14) 5=<5
       Exit: (14) 5=<5
       Call: (14) 5>=0
       Exit: (14) 5>=0
       Exit: (13) valid(0, 5)
       Exit: (12) changeState(s(0, 5), s(0, 0))
    ^  Call: (12) not(member(s(0, 0), [s(0, 5), s(3, 5), s(3, 0), s(0, 0)]))
    ^  Unify: (12) not(user:member(s(0, 0), [s(0, 5), s(3, 5), s(3, 0), s(0, 0)]))
    ^  Fail: (12) not(user:member(s(0, 0), [s(0, 5), s(3, 5), s(3, 0), s(0, 0)]))
       Redo: (12) changeState(s(0, 5), _10164)
       Unify: (12) changeState(s(0, 5), s(0, 5))
       Call: (13) 0>0
       Fail: (13) 0>0
       Redo: (12) changeState(s(0, 5), _10164)
       Unify: (12) changeState(s(0, 5), s(_10148, _10150))
       Call: (13) 5=<2
       Fail: (13) 5=<2
       Redo: (12) changeState(s(0, 5), _10164)
       Unify: (12) changeState(s(0, 5), s(_10148, _10150))
       Call: (13) 5>2
       Exit: (13) 5>2
       Call: (13) _10150 is 5+(5-0)mod 5
       Exit: (13) 5 is 5+(5-0)mod 5
       Call: (13) valid(_10148, 5)
       Unify: (13) valid(_10148, 5)
       Call: (14) _10148=<3
    ERROR: Arguments are not sufficiently instantiated
    ERROR: In:
    ERROR:   [14] _11032=<3
    ERROR:   [13] valid(_11058,5) at *.pl:10
    ERROR:   [12] changeState(s(0,5),s(_11096,5)) at *.pl:17
    ERROR:   [11] traverse(s(0,5),_11124,[s(0,5),...|...]) at *.pl:26
    ERROR:   [10] traverse(s(3,5),_11176,[s(3,5),...|...]) at *.pl:28
    ERROR:    [9] traverse(s(3,0),_11228,[s(3,0),...]) at *.pl:28
    ERROR:    [8] traverse(s(0,0),_11280,[s(0,0)]) at *.pl:28
    ERROR:    [7] <user>
       Exception: (14) _10148=<3 ? Unknown option (h for help)