PROLOG Stack overflow recursive multiply - prolog

multiply(A,0,0).
multiply(A,B,C) :- D is B-1, multiply(A,D,E), C is E+A.
After using this rule once and Prolog returns an answer, if I want it to continue searching (prompts A = 5 ? and I hit ;), Prolog crashes. I don't understand why? Would anyone be able to explain. Thank you.

The problem is,
multiply(A,B,C) :- D is B-1, multiply(A,D,E), C is E+A.
This code does not have the constraint B > 0 that would prevent the stack overflow from occurring.
You can modify the code as,
multiply(A,B,C) :- B > 0, D is B-1, multiply(A,D,E), C is E+A.
Also, this line multiply(A,0,0). gives a singleton warning, so you can possibly change it into multiply(_,0,0)
Note : I wrote the constraint B > 0 thinking that you call the predicate as multiply(5,1,A).

Here is how you can make an endless loop easily:
?- [user].
|: loop(0).
|: loop(X) :- X0 is X - 1, loop(X0).
|: ^D% user://1 compiled 0.01 sec, 2 clauses
true.
?- loop(3).
true ;
After you redo (when you press ;) you backtrack into the second clause with a 0.
Then X0 becomes -1, you go into the recursive loop(X0), and from here on the first clause will never again match.
Try for example querying:
?- loop(-1).
Your version of the infinite loop is not tail-recursive, which means that it will use up the stack eventually. Here is a minimal example:
?- [user].
|: out_of_stack(0, 0).
|: out_of_stack(X, Y) :- X0 is X - 1, out_of_stack(X0, Y0), Y is Y0 + 1.
|: ^D% user://1 compiled 0.01 sec, 2 clauses
true.
?- out_of_stack(3, R).
R = 3 ;
ERROR: Stack limit (1.0Gb) exceeded
ERROR: Stack sizes: local: 1.0Gb, global: 19Kb, trail: 1Kb
ERROR: Stack depth: 11,183,864, last-call: 0%, Choice points: 3
ERROR: Possible non-terminating recursion:
ERROR: [11,183,864] user:out_of_stack(-11183853, _5046)
ERROR: [11,183,863] user:out_of_stack(-11183852, _5066)
So this is what is happening and why Prolog crashes.
To get rid of the problem, do as other have suggested. The other solution is to use 0, s(0), s(s(0)), ... to represent natural numbers.

Related

PROLOG [hand computation]

I am trying to practice hand computations in prolog could you please explain to me and demonstrate a hand computation of this certain question so I can gain more of an understanding.
In a Prolog project involving text processing (not discussed here further) a predicate duplicate/2 has been implemented for duplicating every entry of a list.
Below is an example of what duplicate/2 does:
?- duplicate([w,o,r,d], D).
D = [w,w,o,o,r,r,d,d] .
?- duplicate([], D).
D = [].
below shows the definition of duplicate/2 . Write down hand computations for duplicate/2
duplicate(L, D) :- duplicate(L,[], D). % clause 0
duplicate([], Acc, D) :- reverse(Acc, D). % clause 1
duplicate([H|T], Acc, D) :- duplicate(T, [H, H|Acc], D). % clause 2
(involving the auxiliary predicate duplicate/3 ) such that each of the three
clauses (numbered 0, 1, 2), is performed in the hand computations.
If you allow the computer to help you in hand computation there are two classical approaches to do that:
1) Use a debugger: Most of the Prolog debuggers use the Byrd box model, means it only shows you a selected goal in the process of a resolution proof. Here is a run of a smaller query for a simpler program. Usually the debugger can be switched on by trace:
?- [user].
duplicate([], []).
duplicate([X|Y], [X,X|Z]) :- duplicate(Y,Z).
^D
Yes
?- duplicate([w,o],X).
X = [w,w,o,o]
?- trace.
Yes
?- duplicate([w,o],X).
0 Call duplicate([w,o], X) ?
1 Call duplicate([o], _C) ?
2 Call duplicate([], _F) ?
2 Exit duplicate([], []) ?
1 Exit duplicate([o], [o,o]) ?
0 Exit duplicate([w,o], [w,w,o,o]) ?
X = [w,w,o,o] ;
0 Redo duplicate([w,o], [w,w,o,o]) ?
1 Redo duplicate([o], [o,o]) ?
2 Redo duplicate([], []) ?
2 Fail duplicate([], _F) ?
1 Fail duplicate([o], _C) ?
0 Fail duplicate([w,o], X) ?
No
2) Write a meta interpreter: You can write meta interpreters that deliver a trace, which can be inspected after a run and which give a certificate of the proof the Prolog system found:
This is the normal vanilla interpreter:
solve(true) :- !.
solve((A,B)) :- !, solve(A), solve(B).
solve(A) :- rule(A,B), solve(B).
Here is an interpreter that gives a trace of the applied
clauses, its implemented in DCG:
solve(true) --> [].
solve((A,B)) --> !, solve(A), solve(B).
solve(A) --> {rule(A,B)}, [(A :- B)], solve(B).
Here is an example run for the simplified duplicate query and program again:
rule(duplicate([], []), true).
rule(duplicate([X|Y], [X,X|Z]), duplicate(Y,Z)).
?- solve(duplicate([w,o],X),L,[]).
X = [w,w,o,o],
L = [(duplicate([w,o],[w,w,o,o]) :- duplicate([o],[o,o])),
(duplicate([o],[o,o]) :- duplicate([],[])),
(duplicate([],[]) :- true)]
Bye
Well let's go for a reduced version of your example query duplicate([w], D).
. There's only one rule head, which takes two arguments: the one of clause 0, with L=[w] and D1=D.(1) The body tells us, we should derive duplicate([w],[],D) instead. The head of clause 1 does not match, because [] and [w] cannot be unified. This leaves clause 2: [w] = [H|T] unifies with H=w and T=[] (2), Acc = [] and D2=D. Now our new goal is duplicate([], [w,w], D), which only matches against clause 1 (3). Our goal there is reverse([w,w],D), which is the builtin reverse/2 predicate. It is true if D unifies with the reverse list of [w,w], therefore D=[w,w]. Now we don't have any goals to derive and have found a full derivation. Since we always renamed the rule's variables, the D is still the one from our original query, meaning that D = [w,w] is a correct answer substitution for the query.
I admit I was a bit lazy, with only one duplicated letter, the reversal of the accumulator Acc seems a little pointless. To see why it is necessary, you can try the same derivation for duplicate([x,y],D), where the accumulator should be [y,y,x,x] since the elements are always prepended.
Another interesting exercise is also duplicate(X,[w,w]) and to check why duplicate(X,[w]) fails (Hint: look at the unification problem [w] = [H,H|Acc] ). What's also not contained so far is backtracking: in the case of the query duplicate(X, Y), your goal matches multiple heads and you get more than one solution (actually an infinite number of them).
Have fun playing around!
(1) A rule is true independent of how exactly its variables are named. When we have two variables of the same name D from different rules, we need to rename the D in one of the rules to something else, say D1.
(2) You can check this on the prompt by entering the unification as a query:
1 ?- [w] = [H|T].
H = w,
T = [].
(3) The reason is that the list [H|T] has at least one element, whereas [] doesn't have one. You can again check this on the prompt:
2 ?- [] = [H|T].
false.
duplicate(L, D) :- duplicate(L,[], D). % clause 0
duplicate([], Acc, D) :- reverse(Acc, D). % clause 1
duplicate([H|T], Acc, D) :- duplicate(T, [H, H|Acc], D). % clause 2
quick hand computation below for my understanding please correct me if im wrong and tell me if i am correct because i am new to prolog.
duplicate[w,o,r,d], D) clause 0 --> duplicate ([w,o,r,d],[].D).
clause 2 --> duplicate[w,o,r,d],Acc,D) --> clause 2 duplicate([o,r,d],[w,w],[],D),
i could keep going through clause 2 to keep duplicating the head of the list , i can do this till the list is empty []. then i can move to clause 1.
which i can then put my list in the accumulator then reverse it to produce [d,d,r,r,o,o,w,w]
below is the hand computation of clause 1.
clause 1 duplicate[w,w,o,o,r,r,d,d],D) ---> clause 1 reverse([w,w,o,o,r,r,d,d],D).
D = [d,d,r,r,o,o,w,w]

How to return two values from a basic predicate(?) in Prolog?

I just started going over Prolog about an hour ago and have already stumbled into a slight problem I am unsure about. I am writing a predicate (or function?) that takes a list and returns the min and max values. Right now, I am just looking at one of the special cases when the list has 1 item. For example, if you query minmax([5], X, Y). I want the predicate to return X=5 Y=5. I have this code:
minmax([X], X, X).
but it is returning X = Y, Y = 5. I know it is a true statement and trivial, but is there a way I can return X=5,Y=5 ???
It is returning what you think it is. X is 5 as is Y. The values are unified and so the interpreter shows the message X=Y, Y=5. You need to get out the Prolog textbook and read up on unification of terms.
You could just as easily say
foo(A,B) :- A = 5 , B is (A+A)/2 .
and query it:
?- foo(X,Y).
and get the same result. In the Prolog universe, there is only ever a single instance of the integer 5.
X=Y, Y=5 means that X and Y are now both equal to 5. It's just a different way of saying that; you really shouldn't care. If you print both values, you'll just get 5:
?- [user].
|: print_stuff :-
|: X = Y,
|: Y = 5,
|: write('X = '), writeln(X),
|: write('Y = '), writeln(Y).
|: % user://1 compiled 0.02 sec, 2 clauses
true.
?- print_stuff.
X = 5
Y = 5
true.

Unification of expanded terms, double negation

I need to introduce a predicate that will let me negate atoms. So far I have neg(Premise) :- \+ Premise., which gives me following results:
?- assert(a).
true.
?- a.
true.
?- neg(a).
false.
?- neg(neg(a)).
true.
That makes sense and all is dandy, until I tried unification. For instance
[a,_] = [a,123]. returns true.
while
[a,_] = [neg(neg(a)),123]. returns false..
How can I solve this so that the neg(neg(X)) part is being evaluated or otherwise unified with X (since they both are logically equivalent)? So basically, I need X=neg(a), a=neg(X). to succeed.
Edit I found an explanation as to why not(not(<expression>)) is not equivalent to <expression> in prolog. Since <expression> succeeds, not(<expression>) fails. When a goal fails the variables it instantiated get uninstantiated. (source, slide 14).
I'm still not sure how to get around this though.
Reification of truth value will work on your simple case:
4 ?- [user].
|: reify(P, V) :- call(P) -> V = 1 ; V = 0.
% user://1 compiled 0.03 sec, 2 clauses
true.
5 ?- reify(true, V), reify(\+ \+ true, U), V = U.
V = U, U = 1.
using your symbols:
6 ?- [user].
|: a.
|: neg(P) :- \+ P.
% user://2 compiled 0.02 sec, 3 clauses
true.
7 ?- reify(a, V), reify(neg(neg(a)), U), V = U.
V = U, U = 1.
not sure how well this will merge with your code.

Prolog - Assert into a new database

:-dynamic listofQuestions/2.
myrule:-
write('P = '), write(Percent), write('-'),write(X),
( listofQuestions(Percent,X) -> true ; assert(listofQuestions(Percent,X)) ),
The code snippet might not be required to answer my question.
I want to assert to a blank 'listofQuestions' everytime I call my rule. This only happens if I close my prolog window and restart it.
Any suggestions?
abolish/1 removes all clauses of a given predicate from the database. Hence, just add a call to abolish(PredName/Arity) whenever you need to remove the information about this predicate. Beware that after abolishing the call to the dynamic predicate does not fail but reports an error.
12 ?- f(X,Y).
false.
13 ?- assert(f(a,b)).
true.
14 ?- f(X,Y).
X = a,
Y = b.
15 ?- abolish(f/2).
true.
16 ?- f(X,Y).
ERROR: user://2:67:
toplevel: Undefined procedure: f/2 (DWIM could not correct goal)
In SWI-Prolog, abolish works on static procedures, unless the prolog flag iso is set to true. If you intend to remove only dynamic predicates, you should better try retractall. Observe that in this case removal does not lead to an error being reported but to a failure.
17 ?- [user].
:- dynamic f/2.
|:
% user://3 compiled 0.00 sec, 264 bytes
true.
18 ?- f(X,Y).
false.
19 ?- assert(f(a,b)).
true.
20 ?- f(X,Y).
X = a,
Y = b.
21 ?- retractall(f(X,Y)).
true.
22 ?- f(X,Y).
false.

Prolog syntax - using function results

I am trying to perform a sum operation on every result of :
combination(0,_,[]).
combination(K,L,[X|Xs]) :-
K > 0,
el(X,L,R),
K1 is K-1,
combination(K1,R,Xs).
el(X,[X|L],L).
el(X,[_|L],R) :- el(X,L,R).
For example, the user will enter is_sum_equal_10 ([1,2,3,4,5,6,7]) and the result will be true if the sum of any of the permutations equals 10.
I am struggling with putting it all together, can someone please help me define the is_sum_equal_10 rule that uses the combination rule for each permutation?
OK, well it's pretty easy to write really, you just need a rule to say if a particular combination sums to 10, and then another extra one to count up through the different sizes of combination lists (which is required due to the way you wrote combination with the K that you need to decrease as you check the rule).
1 ?- [user].
|: combination(0,_,[]).
|: combination(K,L,[X|Xs]) :- K > 0,
|: el(X,L,R), K1 is K-1, combination(K1,R,Xs).
|: el(X,[X|L],L).
|: el(X,[_|L],R) :- el(X,L,R).
|:
|: totals_10([],10).
|: totals_10([X|Xs],T) :- N is T+X, totals_10(Xs,N).
|:
|: is_comb_sum_equal_10(Numbers,_,R) :- combination(R,Numbers,C), totals_10(C,0).
|: is_comb_sum_equal_10(Numbers,N,R) :- Rnext is R+1, Rnext =< N,
|: is_comb_sum_equal_10(Numbers,N,Rnext).
|:
|: is_sum_equal_10(Numbers) :- length(Numbers,N), is_comb_sum_equal_10(Numbers,N,0).
|:
% user://1 compiled 0.13 sec, 1,824 bytes
true.
2 ?- is_sum_equal_10([2,3,5]).
true .
3 ?- is_sum_equal_10([2,235,124,3,3347,5,2373]).
true .
4 ?- is_sum_equal_10([2,235,124,3,3347,6,2373]).
false.
5 ?- is_sum_equal_10([1,1,1,1,1,-1,1,1,1,1,12]).
false.
6 ?- is_sum_equal_10([1,1,1,1,1,-1,1,1,1,1,11]).
true ;
false.
Since you don't care about the actual list or how big it is in the is_sum_equal_10 thing, you can just sum the combinations as you go along, and even better, check the sum is correct as a rule for the base case. I think it's a bit neater if you subtract from the desired total to get to 0 at the base rather than adding up and checking at the end against the value you want. This gives you a very simple single ruleset to look for a certain sum.
7 ?- [user].
|: is_subset_sum(0,[]).
|: is_subset_sum(N,[_|Xs]) :- is_subset_sum(N,Xs).
|: is_subset_sum(N,[X|Xs]) :- R is N-X, is_subset_sum(R,Xs).
|:
% user://2 compiled 0.03 sec, 540 bytes
true.
8 ?- is_subset_sum(10,[3,5,6]).
false.
9 ?- is_subset_sum(10,[123,4,1,77,3,2,34]).
true .
10 ?- is_subset_sum(11,[0,2,4,6,8,10,12,14,16,18,20,22]).
false.
This approach is of course both much easier to understand, and a lot more efficient.

Resources