Finding whether a number is a multiple of another - prolog

Looking at the code below:
multiple(X,0).
multiple(X,Y) :- lt(0,X), lt(0,Y), diff(Y,X,D), multiple(X,D).
There happens to be something wrong. For your reference:
lt/2 is whether the first argument is less than the second.
diff/3 is whether the third argument is equal to the first argument minus the second.
lt/2 and diff/3 are defined correctly.
Is there a logical mistake in the definition? Is assuming that 0 is the multiple of every number problematic or is the logical mistake somewhere else? I get correct answers but the query goes to infinite loop I think.
EDIT:
here are the other definitions.
natNum(0).
natNum(s(X)) :- natNum(X).
lt(0,s(X)) :- natNum(X).
lt(s(X),s(Y)) :- lt(X,Y).
sum(0,X,X).
sum(s(X),Y,s(Z)) :- sum(X,Y,Z).
diff(X,Y,Z) :- sum(Z,Y,X).
?- multiple(X, s(s(s(s(s(s(0))))))).
where s(0) is 1, s(s(0)) is 2 etc. It gives all the desired answers for X but after the last answer, it gets stuck. I assume in an infinite recursive loop?

What is happening in your program? Does it loop forever, or does it only take some time since you haven't updated your hardware in recent decades? We cannot tell. (Actually, we could tell by looking at your program, but that is much too complex for the moment).
What we can do with ease is narrow down the source of this costly effort. And this, without a deep understanding of your program. Let's start with the query:
?- multiple(X, s(s(s(s(s(s(0))))))).
X = s(0)
; X = s(s(0))
; X = s(s(s(0)))
; X = s(s(s(s(s(s(0))))))
; loops. % or takes too long
Isn't there an easier way to do this? All this semicolon typing. Instead, simply add false to your query. In this manner the solutions found are no longer shown and we can concentrate on this annoying looping. And, if we're at it, you can also add false goals into your program! By such goals the number of inferences might be reduced (or stays the same). And if the resulting fragment (called a failure-slice) is looping, then this is a reason why your original program loops:
multiple(_X,0) :- false.
multiple(X,Y) :- lt(0,X), false, lt(0,Y), diff(Y,X,D), multiple(X,D).
natNum(0) :- false.
natNum(s(X)) :- natNum(X), false.
lt(0,s(X)) :- natNum(X), false.
lt(s(X),s(Y)) :- false, lt(X,Y).
?- multiple(X, s(s(s(s(s(s(0))))))), false.
loops.
Do your recognize your program? Only those parts remained that are needed for a loop. And, actually in this case, we have an infinite loop.
To fix this, we need to modify something in the remaining, visible part. I'd go for lt/2 whose first clause can be generalized to lt(0, s(_)).
But wait! Why is it OK to generalize away the requirement that we have a natural number? Look at the fact multiple(X,0). which you have written. You have not demanded that X is a natural number either. This kind of over-generalizations often appears in Prolog programs. They improve termination properties at a relatively low price: Sometimes they are too general but all terms that additionally fit into the generalization are not natural numbers. They are terms like any or [a,b,c], so if they appear somewhere you know that they do not belong to the solutions.
So the idea was to put false goals into your program such that the resulting program (failure-slice) still loops. In the worst case you put false at a wrong place and the program terminates. By trial-and-error you get a minimal failure-slice. All those things that are now stroked through are irrelevant! In particular diff/3. So no need to understand it (for the moment). It suffices to look at the remaining program.

Related

Determining successor in prolog using recursion

I'm trying (failing) to understand an exercise where I'm given the following clauses;
pterm(null).
pterm(f0(X)) :- pterm(X).
pterm(f1(X)) :- pterm(X).
They represent a number in binary, eg. f0(null) is equivalent to 0, f1(null) is equivalent to 1, etc.
The objective is to define a predicate over pterm such that one is the successor of the other when true. It seems like a relatively simple exercise but I'm struggling to get my head around it.
Here is the code I've written so far;
incr(X,Y) :- pterm(f0(X)), pterm(f1(Y)).
incr(X,Y) :- pterm(f0(f1(X))), pterm(f1(f1(Y))).
Having tested this I know it's very much incorrect. How might I go about inspecting the top level arguments of each pterm?
I've made minimal progress in the last 4 hours so any hints/help would be appreciated.
1)
I'll start with the "how to inspect" question, as I think it will be the most useful. If you're using swi-prolog with xpce, run the guitracer:
?- consult('pterm'). % my input file
% pterm compiled 0.00 sec, 5 clauses
true.
?- guitracer.
% The graphical front-end will be used for subsequent tracing
true.
?- trace. % debugs step by step
true.
[trace] ?- pterm(f0(f1(null))). % an example query to trace
true.
A graphical interface will come up. Press the down arrow to unify things step by step. What's going on should make sense fairly quickly.
(use notrace. and nodebug. appropriately to exit trace and debug modes afterwards).
2) You seem to misunderstand how predicates work. A predicate is a logical statement, i.e. it will always return either true or false. You can think of them as classical boolean functions of the type "iseven(X)" (testing if X is even) or "ismemberof(A,B)" (testing if A is a member of B) etc. When you have a rule like "pred1 :- pred2, pred3." this is similar to saying "pred1 will return true if pred2 returns true, and pred3 returns true (otherwise pred1 returns false)".
When your predicates are called using constants, checking its truth value is a matter of checking your facts database to see if that predicate with those constants can be satisfied. But when you call using variables, prolog goes through a wild goose chase, trying to unify that variable with all the allowable stuff it can link it to, to see if it can try to make that predicate true. If it can't, it gives up and says it's false.
A predicate like incr(X,Y) is still something that needs to return true or false, but, if by design, this only becomes true when Y is the incremented version of X, where X is expected to be given at query time as input, then we have tricked prolog into making a "function" that is given X as input, and "returns" Y as output, because prolog will try to find an appropriate Y that makes the predicate true.
Therefore, with your example, incr(X,Y) :- pterm(f0(X)), pterm(f1(Y)). makes no sense, because you're telling it that incr(X,Y) will return true for any X,Y, as long as prolog can use X to find in the fact database any pterm(f0(X)) that will lead to a known fact, and also use Y to find a pterm(f1(Y)) term. You haven't made Y dependent on X in any way. This query will succeed for X = null, and Y = null, for instance.
Your first clause should be something like this.
incr(X,Y) :- X = pterm(f0(Z)), Y = pterm(f1(Z)).
where = performs unification. I.e. "find a value for Z such that X is pterm(f0(Z)), and for the same value of Z it also applies that Y = pterm(f1(Z))."
In fact, this could be more concisely rewritten as a fact:
incr( pterm(f0(Z)), pterm(f1(Z)) ).
3)
Your second clause can be adapted similarly. However, I'm not sure if this is correct in terms of the logic of what you're trying to achieve (i.e. binary arithmetic). But I may have misunderstood the problem you're trying to solve.
My assumption is that if you have (0)111, then the successor should be 1000, not 1111. For this, I would guess you need to create a predicate that recursively checks if the incrementation of the digits below the currently processed one results in a 'carried' digit.
(since the actual logic is what your assignment is about, I won't offer a solution here. but hope this helps get you into grips with what's going on. feel free to have a go at the recursive version and ask another question based on that code!)

Find adjacent members

I have to find if two members of a list are adjacent. The restriction is to use the append/3 predicate. So far I've done the below, it works if it's true, otherwise I get no answer, it's like it runs eternally.
adjacent(X,Y,L):-
append(L1,[X,Y],T1),append(T1,T2,L).
To see that your program will loop, it suffices to consider the following failure-slice:
adjacent(X,Y,L):-
append(L1,[X,Y],T1), false,
append(T1,T2,L).
If this program will loop, then the original program will loop too. It might succeed, but still it will loop.
In your first goal both L1 and T1 are uninstantiated variables - that's easy to see, because they are not used anywhere else in this fragment. As a consequence, this program will always loop, no matter what X, Y or L might be. To fix this, you have to modify something in the visible part.
One possibility would be to exchange the two goals. But there is an even easier way out:
adjacent(X,Y,L) :-
append(_,[X,Y|_],L)
Note however, that this does not ensure that L is really a well formed list. In fact, adjacent(1,2,[1,2|nonlist]) succeeds. In case it should be a list:
adjacent(X,Y,L) :-
append(_,[X,Y|R],L),
append(R,[],R).
See failure-slice for more.
This might not be the best answer, but you can also try:
adjacent(X,Y,Zs):- append(As,[X,Y|Ys],Zs).
For example:
3 ?- adjacent(1,2,[1,2,3]).
true .
1 ?- adjacent(1,3,[1,2,3]).
false.

Prolog Backtracking On Finding A Solution And Returning False

I'm taking a crack at Prolog (using SWI-Prolog) and everything works like I want it to, i.e., the logic is calculated correctly and it finds the right solutions but the whole backtracking thing is screwing with me.
Here's the code:
tall(X) :- skinny(X) ; eatless(X).
eatless(X) :- playsmore(X).
playsmore(X) :- hasxbox(X) ; hasplaystation(X).
skinny(a).
vegetarian(a).
hasxbox(b).
eatsburger(c).
hasplaystation(d).
list_all_tall :- forall(tall(Tall), writeln(Tall)).
Very basic stuff. Here's what I get as a result of my queries:
?- tall(a).
true ; % Note 1
false.
?- tall(b).
true ; % Note 2
false.
?- tall(c).
false.
?- tall(d).
true.
As you can see from Notes 1 and 2, it waits for me to hit ; to move on and then considers the first solution as null and eventually outputs false.
I can use cuts to control this behavior better but I also want the following commands to work properly:
?- tall(X).
X = a ;
X = b ;
X = d.
And:
?- list_all_tall.
a
b
d
true.
These two commands give the solution exactly the way I want. Its just the ones for Notes 1 and 2 that are driving me up the wall. Is there a way that I can keep the functionality as it is right now for tall(X). and list_all_tall., while fixing the functionality of tall(a). and tall(b). to my liking, i.e., the program should exit with a true. after I ask tall(a). or tall(b).
I'd appreciated it if instead of giving straight answers someone could actually explain how I could go about fixing it myself because maybe my way of thinking in Prolog is all bassackwards.
PS: No offense intended to tall, skinny, fat, burger eating, video game playing, vegetarian folks.
Just to supplement Daniel's well-explained answer (+1) for your specific case, consider:
tall(a).
Prolog will look at the first match, which is through:
tall(X) :- skinny(X) ; eatless(X).
This will succeed because skinny(a) will succeed. However, there's a disjunction ; leaving a choice point for Prolog that it hasn't explored yet. Because skinny(a) succeeds and the choice point is pending, you get true but prompted to seek more. Prolog then backtracks to the choice point and tries to satisfy eatless(a) but fails. Thus, you get:
?- tall(a).
true ; % because `skinny(a)` succeeded
false. % because `eatless(a)` failed
Taking another example:
tall(d).
Again, this matches the tall/1 predicate, but this time, skinny(d) fails and prolog moves right on (due to the disjunction) to eatless(d) which succeeds. However, there are no more choice points after that success, so you get:
?- tall(d).
true. % There were no choice points available after success
The best thing to do is not worry about it, because you're not always going to be able to prevent it.
Prolog doesn't ever know that there will be another answer. It just knows that there may be another answer. This is called a choice point. Whenever Prolog reaches an alternative, it creates a choice point and then follows the first option. If that option doesn't work out, it backs up to the most recent choice point and tries the next alternative. If it runs out of alternatives without finding an answer, you get no or false.
You can try to write your code so that you don't get a choice point if you know there are no more items. member/2, for instance, in some Prologs you get false after the last item and in others you do not. But it isn't a composition problem to have a dud choice point after all your solutions. Your user interface probably won't show users Prolog's prompts directly. You can use setof/3 and the other extralogical predicates to get all the solutions. The false won't "leak" out into the world. It's a little unnerving at first, but just trust it and don't worry too much about it.
It is possible to run the same predicate, tall/1 in this case, in different modes based on different instantiation patterns.
When you run ?- tall(a). you instantiate the argument (i.e., X=a) and you want to receive either true or false (and no choicepoints, indicated by ;).
In Prolog this mode is called semi-deterministic.
You can force your predicate to be semi-deterministic for this specific instantiation pattern in the following way:
tall(X):- (ground(X) -> once(tall0(X)) ; tall0(X)).
Here ground(X) succeeds just in case X is fully instantiated.
Fully instantiated means that it is not a variable nor is it a compound term containing a variable.
tall0(X) is your original predicate.
The second mode you want to use is ?- tall(X).
Here you expect all results to be given subsequently, using ;.
This mode is called non-deterministic in Prolog.
The complete code for your example is:
tall(X):- (ground(X) -> once(tall0(X)) ; tall0(X)).
tall0(X):- skinny(X) ; eatless(X).
eatless(X):- playsmore(X).
playsmore(X):- hasxbox(X) ; hasplaystation(X).
skinny(a).
hasxbox(b).
hasplaystation(d).
Now the single predicate tall/1 can be called in the two modes, producing the behavior you want. Semi-deterministic usage:
?- tall(a).
true.
Non-deterministic usage:
?- tall(X).
X = a ;
X = b ;
X = d.
Hope this helps!

prolog dcg restriction

I would like to use DCGs as a generator. As of now, the syntax is
s-->a,b.
a-->[].
a-->a,c.
c-->[t1].
c-->[t2].
b-->[t3].
b-->[t4].
I would like to generate all s where the length of a is < someNumber.
Using ?- phrase(a,X),length(X,Y),Y<4. i can get all a with less than 4 items. However, when all combinations are exhausted, the system (SWI-Prolog 6.2.5) seems to stall.
Sometimes ago, a similar question was asked here. However, being new to Prolog i am not able to make it work with the grammar above. Any ideas?
Update: There was a comment by (canrememberthename) which got deleted, somehow. Anyway, it was suggested to use between(1,4,Y),length(X,Y),phrase(a,X). to set limits. This worked nicely, after changing my code to a-->c,a.
The first steps into Prolog are often a bit difficult. But you are on the right track:
Currently, your problem is that you get some answers/solutions as expected but then the system stalls ; in fact, it is in an infinite loop. You found that out by patiently hitting SPACE. That might work with a tiny set of solutions but it will be tedious with a larger one. Just think of looking at all sentences shorter than 20.
There is a simple keyboard and carpal tunnel friendly way to simulate hitting space: Simply add a goal false at the end like so:
?- phrase(a,X),length(X,Y),Y<4, false.
What could Prolog answer to such a question? Since there is false at the end, Prolog has not much choice: Either it answers false itself ; or it loops (or produces an error or produces some side-effect). And in this case, it loops.
Now, we can narrow down the problem, by adding further false goals into your program.
?- phrase(a,X),length(X,Y),false, Y<4, false.
loops.
To make this better readable, I will only use one false goal and strike through the remaining part of the query:
?- phrase(a,X),length(X,Y),false, Y<4.
loops.
Let's reduce that even further:
?- phrase(a,X),false,length(X,Y),Y<4.
loops.
They all loop! But we get some interesting insight: Since these false-adorned queries do not terminate, also the original program does not terminate. So when you look at a query, and the very first goal does not terminate for itself, it follows that the entire query will not terminate (see the fine print at the end for more).
Therefore: You have to address the first goal somehow!
My first attempt is to exchange length and phrase:
?- length(X,Y), phrase(a,X), Y<4.
Will this work? Just look at the first goal which loops:
?- length(X,Y), false, phrase(a,X), Y<4.
loops.
So this again will not terminate.
You have to change the program again:
?- between(1,3,Y), length(X,Y), false, phrase(a,X).
false.
So this terminates. And if there will be a termination problem, phrase(a,X) has now to take the blame:
?- between(1,3,Y), length(X,Y), phrase(a,X), false.
loops.
You might be tempted to look at actual answers:
?- between(1,3,Y), length(X,Y), phrase(a,X).
Y = 1, X = [t1]
; Y = 1, X = [t2]
; resource_error(local_stack). % ERROR: Out of local stack
And you might conclude that this behavior is worse than your original definition. After all, we have now less answers than before. But exactly that kind of reasoning does not help you to improve termination: With false both are of the same kind of incorrectness and you have to address this first. So by hiding the answers you can better concentrate on the rest.
But why is your grammar problematic? We can continue with our technique to insert goals false to narrow it down. But this time within your grammar. Your program adorned with goals false is called a failure-slice.
Just a practical remark: When I insert goals false into your program, I will save the program and type make in SWI: In this manner the program is rapidly recompiled.
After trying a bit, I got the following minimal failure-slice. Note that within a DCG, false has to be written as {false}.
?- between(1,3,Y), length(X,Y), phrase(a,X), false
s--> {false}, a,b.
a-->[], {false}.
a-->a,{false}, c.
c-->{false}, [t1].
c-->{false}, [t2].
b-->{false}, [t3].
b-->{false}, [t4].
Almost all your codebase are belong to false! So you have to address the tiny visible remaining part. It would be pointless to change something somewhere else. This a --> a, ... must be changed! And in fact changing it to a --> c, s solves the problem.
Why did you write a --> a, c. in the first place? I suspect that you wanted to enumerate all solutions in a fair manner. The new version doesn't:
?- phrase(a,X).
X = []
; X = [t1]
; X = [t1,t1]
; X = [t1,t1,t1]
; X = [t1,t1,t1,t1]
; X = [t1,t1,t1,t1,t1]
; X = [t1,t1,t1,t1,t1,t1]
; X = [t1,t1,t1,t1,t1,t1,t1]
; ... .
That looks very intimidating. In fact, it looks wrong. Doesn't it? But don't let you confuse by this: We have here an infinite set of sentences. So the only correct response by Prolog is to produce infinitely many answers. For, if they would be finite, some list would be missing! But of course, you want to see them enumerated in a fair manner. To get this, simply write:
?- length(X,N), phrase(a,X).
X = [], N = 0
; X = [t1], N = 1
; X = [t2], N = 1
; X = [t1,t1], N = 2
; X = [t1,t2], N = 2
; X = [t2,t1], N = 2
; X = [t2,t2], N = 2
; X = [t1,t1,t1], N = 3
; ... .
This is a major point in Prolog programs: Always go for the best (possible) termination property first. And do not look at the precise order how Prolog enumerates answers. For, if a program has better termination properties, it is next-to-trivial to use it to enumerate all solutions in a fair manner. But: A program that enumerates infinitely many solutions in a fair manner at the expense of termination cannot be used in more interesting cases.
Fine Print See this answer.
the nonterminal a//0 is both left recursive and 'epsilon' (generate the empty sequence), and phrase/2 will loop immediately after the empty production.
You can solve your problem bounding list' length:
?- between(1,4,Y),length(X,Y),phrase(a,X).
and, as you have already done, removing the left recursion.

DCG and left recursion

I am trying to implement a dcg that takes a set of strings of the form {a,b,c,d}*.The problem i have is if I have a query of the form s([a,c,b],[]),It returns true which is the right answer but when i have a query of the form s([a,c,f],[]),It does not return an answer and it runs out of local stack.
s --> [].
s --> s,num.
num --> [a].
num--> [b].
num--> [c].
num--> [d].
Use phrase/2
Let's try phrase(s,[a,b,c]) in place of s([a,b,c],[]). The reason is very simple: In this manner we are making clear that we are using a DCG (dcg) and not an ordinary predicate. phrase/2 is the "official" interface to grammars.
So your first question is why does phrase(s,[a,c,f]) not terminate while phrase(s,[a,b,c]) "gives the right answer" — as you say. Now, that is quick to answer: both do not terminate! But phrase(s,[a,b,c]) finds a solution/answer.
Universal termination
These are two things to distinguish: If you enter a query and you get an answer like true or X = a; you might be interested to get more. Usually you do this by entering SPACE or ;ENTER at the toplevel. A query thus might start looping only after the first or several answers are found. This gets pretty confusing over time: Should you always remember that this predicate might produce an answer ; another predicate produces two and only later will loop?
The easiest way out is to establish the notion of universal termination which is the most robust notion here. A Goal terminates iff Goal, false terminates. This false goal corresponds to hitting SPACE indefinitely ; up to the moment when the entire query fails.
So now try:
?- phrase(s,[a,c,f]), false.
loops.
But also:
?- phrase(s,[a,b,c]), false.
loops.
From the viewpoint of universal termination both queries do not terminate. In the most frequent usage of the words, termination is tantamount to universal termination. And finding an answer or a solution is just that, but no kind of termination. So there are queries which look harmless as long as you are happy with an answer but which essentially do not terminate. But be happy that you found out about this so quickly: It would be much worse if you found this out only in a running application.
Identify the reason
As a next step let's identify the reason for non-termination. You might try a debugger or a tracer but most probably it will not give you a good explanation at all. But there is an easier way out: use a failure-slice. Simply add non-terminals {false} into your grammar ; and goals false into predicates. We can exploit here a very beautiful property:
If the failure-slice does not terminate then the original program does not terminate.
So, if we are lucky and we find such a slice, then we know for sure that termination will only happen if the remaining visible part is changed somehow. The slice which is most helpful is:
?- phrase(s,[a,b,c]), false
s --> [], {false}.
s --> s, {false}, num.
There is not much left of your program! Gone is num//0! Nobody cares about num//0. That means: num//0 could describe anything, no matter what — the program would still loop.
To fix the problem we have to change something in the visible part. There is not much left! As you have already observed, we have here a left recursion. The classical way to fix it is:
Reformulate the grammar
You can easily reformulate your grammar into right recursion:
s --> [].
s --> num, s.
Now both queries terminate. This is the classical way also known in compiler construction.
But there are situations where a reformulation of the grammar is not appropriate. This simple example is not of this kind, but it frequently happens in grammars with some intended ambiguity. In that case you still can:
Add termination inducing arguments
?- Xs = [a,b,c], phrase(s(Xs,[]), Xs).
s(Xs,Xs) --> [].
s([_|Xs0],Xs) --> s(Xs0,Xs1), num, {Xs1=Xs}.
Inherently non-terminating queries
Whatever you do, keep in mind that not every query can terminate. If you ask: »Tell me all the natural numbers that exist – really all of them, one by one!« Then the only way to answer this is by starting with, say, 0 and count them up. So there are queries, where there is an infinity of answers/solutions and we cannot blame poor Prolog to attempt to fulfill our wish. However, what we most like in such a situation is to enumerate all solutions in a fair manner. We can do this best with a grammar with good termination properties; that is, a grammar that terminates for a list of fixed length. Like so:
?- length(Xs, M), phrase(s, Xs).
For about other examples how to apply failure-slices, see tag failure-slice.
I don't know if this is any help, because the prolog I'm using seems to have a very different syntax, but I just wrote the following program to try and match yours and it works ok.
Program
s([]).
s([X|Xs]) :- num(X), s(Xs).
num(a).
num(b).
num(c).
num(d).
Output
?- [prologdcg].
% prologdcg compiled 0.00 sec, 2,480 bytes
true.
?- s([a,c,b]).
true.
?- s([a,c,f]).
false.
Run using SWI-prolog.

Resources