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.