'Arguments are not sufficiently instantiated' - prolog

The problem I'm trying to solve is finding how many of different types of coins is needed to pay for a given sum, if any solutions exist.
Here's my knowledge base:
payment(0, _).
payment(Total, [coin(AmountNeeded,ValueOfCoin,AmountAvailable)|Tail]) :-
AmountNeeded in 0..AmountAvailable,
Total #= SubTotal + ValueOfCoin*AmountNeeded,
payment(SubTotal, Tail).
When I do the query
payment(25, [coin(Ones,1,11),coin(Fives,5,4),coin(Tens,10,3),coin(Twenties,20,2)]).
I get an answer:
Fives in 3..4,
_3198#=5*Fives,
_3198 in 15..20,
Ones+_3198#=25,
Ones in 5..10
And so on, but when I add label to the query, like this
payment(25, [coin(Ones,1,11),coin(Fives,5,4),coin(Tens,10,3),coin(Twenties,20,2)]),
label([Ones, Fives, Tens, Twenties]).
I get an error saying 'Arguments are not sufficiently instantiated'. From what I've found this means that there are still unbound variables. The way I understand my code it should recrusively unfold like this:
payment(25, [coin(Ones,1,11),coin(Fives,5,4),coin(Tens,10,3),coin(Twenties,20,2)]).
\/
Ones in 0..11
25 #= SubTotal' + 1*Ones
Fives in 0..4
(25-1*Ones) #= SubTotal'' + 5*Fives
Tens in 0..3
(25-1*Ones-5*Fives) #= SubTotal''' + 10*Tens
Twenties in 0..2
(25-1*Ones-5*Fives-10*Tens) #= SubTotal'''' + 20*Twenties
So I think it's at this point that it breaks down, since the SubTotal'''' variable is not assigned in the end. But how do I deal with this? Am I missing some base case? The code works for a single coin, but with more than one coin there's always one variable left unassigned.

Related

Unexpected duplicate result when creating all combinations for n bits

I need to learn Prolog for College, and gave myself a task to solve a single line of a Nonogram (https://en.wikipedia.org/wiki/Nonogram).
I am using 'x' as 'o' as characters for a filled or an empty field, and a brute force approach to, as a first step, find every combination in that line, regardless of the Nomogram rules. This step is really the same as finding every combination of n bits, like 000 001 010 011 100 101 110 111 with n=3. I am going to weed out the matching combinations according to Nomogram rules afterwards, in fact I got this bit of code working already. This is surely not efficient, but I am glad I got this far.
If there is a very easy approach, to solve all options for a line, according to the rules for the line, in a "forward" approach opposed to this brute force approach, I would love to learn how this can be done. Rules would be something like (10, [4,3]) meaning the row has 10 places, and 2 groups of 4 and 3 blocks. But since this is "just for fun", don't bother much with writing it, please!
The code below works - but it finds every combination twice, and I cannot find out why. Any idea what makes it list everything twice? If there are mayor no-nos in that code (there are for sure!), please feel free to point them out. I am just a couple of hours into the language, and still try to "force" the style for implicit or object oriented languages, with little success :)
count_list([], 0). % Count Elements in a List
count_list([_|T], C) :-
count_list(T, C1),
C is 1 + C1.
append_list(X, [], [X]). % Attach a new Element as first to a List
append_list(X, List, [X|List]).
zeichen(x).
zeichen(o).
nonoline_generator(N, PartIn, Line) :- % Add x and o to the combination, except the last one
count_list(PartIn, C),
N > C + 1,
zeichen(X),
append_list(X, PartIn, PartAppended),
nonoline_generator(N, PartAppended, Line).
nonoline_generator(N, PartIn, Line) :- % Add the last x or o to the line
count_list(PartIn, C),
N =:= C + 1,
zeichen(X),
append_list(X, PartIn, Line).
% Usage:
nonoline_generator(2, [], Out).
% gives (well... all double, at the moment)
% [x,x]
% [x,o]
% [x,x]
% [x,o]
% [o,x]
% [o,o]
% [o,x]
% [o,o]
Thanks a lot for any comments!
If all you want to do is fill in a list with x's or o's:
bits([]).
bits([x|Rest]) :- bits(Rest).
bits([o|Rest]) :- bits(Rest).
?- length(B, 3),
forall(bits(B),
format('~q~n', [B])).
[x,x,x]
[x,x,o]
[x,o,x]
[x,o,o]
[o,x,x]
[o,x,o]
[o,o,x]
[o,o,o]

Number of legs and heads from Horse and Men in Prolog - RIDDLE

I am currently trying to solve a riddle:
"How many men and horses have 8 heads and 20 feet?"
As I am trying to solve this question with Prolog, my attempt was:
puzzle(M,H,M+H,M*2 + H*4).
And then running:
puzzle(M, H,8,20).
Unfortunately, swipl just returns false.
Can anybody say, why prolog is not working as I was expecting?
To anyone that is interested in a working solution:
horsemen(Man, Horse, Heads, Legs) :-
between(0, Legs, Man),
between(0, Legs, Horse),
Legs is 2*Man + 4*Horse, Heads is Man + Horse.
Anyway, I can't really understand, why the easier solution is not working.
If you write your expression like this:
puzzleSimple(M,M+2).
Prolog will return true for a statement like this :
puzzleSimple(3,3+2). or puzzleSimple(M,M+2).
But it will return false for puzzleSimple(3,5). What you see here is that, prolog will not execute the M+2as an arithmetic operation but rather use it in pattern matching. For arithmetic operations, you need to use the is keyword. For example:
puzzleSimple(M,V):-
V is M + 2.
This code will return true for puzzleSimple(3,5). So, when you try to directly use
puzzle(M,H,M+H,M*2 + H*4). and call puzzle(M, H,8,20).
It returns false, because the pattern is not matching.
You can also modify the code to this:
puzzle(M,H,X,Y):-
X is M+H,
Y is M*2 + H*4.
Now it will be correct in the sense of pattern matching and arithmetic operations. However, when you again call puzzle(M, H,8,20). You will see an Arguments are not sufficiently instantiated error. Why? Because you tried to do an arithmetic operation with a variable which is not instantiated. That is why the working solution uses the predicate between/3. Between assigns a value to a variable and enables the use of backtracking for finding multiple solutions.
Note : Using the gtrace command in swipl can help you in debugging your code!
You can solve it using the library "CLP(FD) Constraint Logic Programming over Finite Domains".
:-use_module(library(clpfd)).
%% "How many men and horses have 8 heads and 20 feet?"
men_and_horses(Men, Horses):-
Men in 0..10,
Horses in 0..10,
Men + Horses #= 8, %% heads must be 8
Men * 2 + Horses * 4 #= 20. %% feet mus be 20
The solution is
?- men_and_horses(X,Y).
X = 6,
Y = 2.

Sum of the first n numbers in prolog

Hello can anyone help me compute the sum of the first n numbers. For example n=4 => sum = 10.
So far I've wrote this
predicates
sum(integer,integer)
clauses
sum(0,0).
sum(N,R):-
N1=N-1,
sum(N1,R1),
R=R1+N.
This one works but I need another implementation. I don't have any ideas how I could make this differen . Please help
What #mbratch said.
What you're computing is a triangular number. If your homework is about triangular numbers and not about learning recursive thinking, you can simply compute it thus:
triangular_number(N,R) :- R is N * (N+1) / 2 .
If, as is more likely, you're learning recursive thought, try this:
sum(N,R) :- % to compute the triangular number n,
sum(N,1,0,R) % - invoke the worker predicate with its counter and accumulator properly seeded
.
sum(0,_,R,R). % when the count gets decremented to zero, we're done. Unify the accumulator with the result.
sum(C,X,T,R) :- % otherwise,
C > 0 , % - assuming the count is greater than zero
T1 is T+X , % - increment the accumulator
X1 is X+1 , % - increment the current number
C1 is C-1 , % - decrement the count
sum(C1,X1,T1,R) % - recurse down
. % Easy!
Edited to add:
Or, if you prefer a count down approach:
sum(N,R) :- sum(N,0,R).
sum(0,R,R). % when the count gets decremented to zero, we're done. Unify the accumulator with the result.
sum(N,T,R) :- % otherwise,
N > 0 , % - assuming the count is greater than zero
T1 is T+N , % - increment the accumulator
N1 is N-1 , % - decrement the count
sum(N1,T1,R) % - recurse down
. % Easy!
Both of these are tail-recursive, meaning that the prolog compiler can turn them into iteration (google "tail recursion optimization" for details).
If you want to eliminate the accumulator, you need to do something like this:
sum(0,0).
sum(N,R) :-
N > 0 ,
N1 is N-1 ,
sum(N1,R1) ,
R is R1+N
.
A little bit simpler, but each recursion consumes another stack frame: given a sufficiently large value for N, execution will fail with a stack overflow.
sum(N, Sum) :-
Sum is (N + 1) * N / 2 .
Since you already got plenty of advice about your code, let me throw in a snippet (a bit off-topic).
Counting, and more generally, aggregating, it's an area where Prolog doesn't shine when compared to other relational,declarative languages (read SQL). But some vendor specific library make it much more pleasant:
?- aggregate(sum(N),between(1,4,N),S).
S = 10.
This is the "heart" of your program:
sum(N,R):-
R=R+N,
N=N-1,
sum(N,R).
The =/2 predicate (note the /2 means it accepts 2 arguments) is the instantiation predicate, not an assignment, or logical equal. It attempts to unify its arguments to make them the same. So if N is anything but 0, then R=R+N will always fail because R can never be the same as R+N. Likewise for N=N-1: it will always fail because N and N-1 can never be the same.
In the case of =/2 (unification), expressions are not evaluated. They are just terms. So if Y = 1, then X = Y + 1 unifies X with 1+1 as a term (equivalently written +(1,1)).
Because of the above issues, sum will always fail.
Numerical assignment of an arithmetic expression is done in Prolog with the is/2 predicate. Like this:
X is Y + 1.
This operator unifies the value of X to be the same as the value of the evaluated expression Y+1. In this case, you also cannot have X is X+1 for the same reason given above: X cannot be made the same as X+1 and Prolog does not allow "re-instantiation" of a variable inside of a clause. So you would need something like, X1 is X + 1. Also note that for is/2 to work, everything in the expression on the right must be previously instantiated. If any variables in the expression on the right do not have a value, you will get an instantiation error or, in the case of Turbo Prolog, Free variable in expression....
So you need to use different variables for expression results, and organize the code so that, if using is/2, variables in the expression are instantiated.
EDIT
I understand from Sergey Dymchenko that Turbo Prolog, unlike GNU or SWI, evaluates expressions for =/2. So the = will work in the given problem. However, the error regarding instantiation (or "free variable") is still caused by the same issue I mentioned above.
sum(N, N, N).
sum(M, N, S):-
N>M,
X is M+1,
sum(X, N, T),
S is M+T.
?- sum(1,5,N).
N = 15 .

using arithmetic operations in Prolog

I have the following code:
position(0,0).
move(f):-
position(X,Y),
number(X),
number(Y),
Y is Y+1,
X is X+1.
but when i call move(f) it returns false. number(X) and number(Y) returns true but whem i add the other two lines the function doesn't work. what's the problem?
Elaborating on some of the comments your question has received, variables in Prolog stand for a possible instantiation of a single value, just like variables in mathematics and mathematical logic, and once they are instantiated within a context they must remain consistent. If we're dealing with a formula 0 = (a + b) - (a + b), we know that it can only express its intended sense if any value assigned to the first a is also assigned to the second. That is, we can substitute any value for a, but it must be the same value throughout. Prolog works with variables in this same way. If x = x + 1, then 2 = 3; but then math would be broken.
Addressing mat's caution against using dynamic predicates, here is a possible way of handling moves, but accomplished by passing around a list of previous moves. With this method, the most recent move will always be the first element of List in the compound term moves(List).
Supposing the current history of moves is as follows:
moves([position(0,0), position(0,1), position(1,1)]).
move/3 takes a direction, a complex term representing the previous moves, and tells us what the updated list of moves is.
move(Direction, moves([From|Ms]), moves([To,From|Ms])) :-
move_in_direction(Direction,From,To).
move_in_direction/3 takes a direction, and a position, and tells us what the next position in that direction is:
move_in_direction(left, position(X1,Y1), position(X2,Y1)) :- X2 is X1 - 1.
move_in_direction(right, position(X1,Y1), position(X2,Y1)) :- X2 is X1 + 1.
move_in_direction(up, position(X1,Y1), position(X1,Y2)) :- Y2 is Y1 + 1.
move_in_direction(down, position(X1,Y1), position(X1,Y2)) :- Y2 is Y1 - 1.
Notice that, using this method, you get a back-trackable history of moves for free. I'd imagine you could use this in interesting ways -- e.g. having the player explore possible series of moves until a certain condition is met, at which point it commits or backtracks. I'd be interested to know what kind of solution you end up going with.

how to solve when the number of variables in the goal/query varies - Prolog Constrain Solver

Here's a snippet on the classic SENDMORY crypt-arithmetic problem solutiong using prolog constraint solving mechanism-
:- lib(ic).
sendmore(Digits) :-
Digits = [S,E,N,D,M,O,R,Y],
Digits :: [0..9],
alldifferent(Digits),
S #\= 0,
M #\= 0,
1000*S + 100*E + 10*N + D
+ 1000*M + 100*O + 10*R + E
#= 10000*M + 1000*O + 100*N + 10*E + Y,
labeling(Digits).
Now, to execute this, I would send a goal/query like this:
?- sendmore(Digits).
And that would return me the possible solutions for the digits.
Now, my question is, I do not want to sort of "hard-code" the variables (like S,E,N,...) this way, but the goal/query would give the number of variables. For example, if the query I pass is something like:
?- sendmore(S,E,N,D,M).
then, it should compute only the values of SENDM and assume that the other variables are not applicable, and hence assign 0 to those variables and then proceed with the computation. And the next time I query, I may pass a different number of variables in the query.. like example:
?- sendmore(S,N,D,M,O,Y).
and the program should compute likewise.
What I am trying to achieve is a more generalised problem solver for the above scenario. Any directions on this is really appreciated. I am quite new to prolog,and am using ECLIPSE constraint solver.
Thank You.
Here are 2 ideas:
You can define sendmore() with different numbers of parameters, which would call the "real" version with the missing ones filled in. But you couldn't have different versions with the same NUMBER of parameters but DIFFERENT ones (since Prolog matches args to parameters by position).
You could expand/complicate your list format to allow the specification of which parameters you are passing; something line [(s,S),(e,E),(n,N),(d,D),(m,M)] for your middle example. A little tedious, but gives you the flexibility you seem to want.
Normally, variables in a goal and variables in a clause head are matched by their positions, not their names. So a call ?- sendmore0([S,E,N,D,M]). should be implemented as:
sendmore0([S,E,N,D,M]) :- sendmore([S,E,N,D,M,_,_,_]).
However, this would mean that you would need to implement this for every possible combination.
If you really want to implement what you describe, then you need to give the variable stable names. In ECLiPSe, you can do this with the library var_name. It's quite a hack, though...
:- lib(var_name).
sendmore0(L) :-
build_arg(["S","E","N","D","M',"O","R","Y"], L, A),
sendmore(A).
build_arg([], _, []) :- !.
build_arg([H|T], L, [HA|HT]) :-
match_arg(L, H, HA),
build_arg(T, L, HT).
match_arg([], _, _). % or use 0 as last argument if you want
match_arg([H|T], Base, A) :-
(
get_var_name(H, S),
split_string(S,"#","",[Base,_])
->
A = H
;
match_arg(T, Base, A)
).
Then you can call sendmore0/1 with a shorter list of variables. Don't forget to set the variable names!
?- set_var_name(S, "S"), set_var_name(E, "E"), sendmore0([S, E]).
S = 9
E = 5
Yes (0.00s cpu, solution 1, maybe more)
Disclaimer: this is not what stable names are for. They are meant for debugging purposes. If Joachim ever sees this, he'll give me a sharp clip round the ears...

Resources