Prolog methods not calling base case - prolog

I am trying to build a program that takes two integers (for example, 4 and 15) and returns the multiples of the first integer that divide into the second integer.
My program is as follows:
divisible(D,U,X):-
divisible_ext(D,U,D,X).
divisible_ext(D,U,D,X):-
U < D,
!.
divisible_ext(D,U,S,X):-
U > D,
D1 is D + S,
divisible_ext(D1,U,S,X1),
X is D.
As far as I am aware, my program should fail the base case with each call until the D value is greater than U (so with 4 and 15, 16 > 15). However in the trace, I can see that the base case is only called the first time, and then never again. Thus when D = 16, the U > D call fails and the entire program fails.
Why is the base case only being called once? Is there something I am not understanding about Prolog that I need to know, or is there a change to my code that I should make?
Edit: Here is my trace:
[trace] 20 ?- divisible(4,15,X).
Call: (7) divisible(4, 15, _G9543) ? creep
Call: (8) divisible_ext(4, 15, 4, _G9543) ? creep
Call: (9) 15<4 ? creep
Fail: (9) 15<4 ? creep
Redo: (8) divisible_ext(4, 15, 4, _G9543) ? creep
Call: (9) 15>4 ? creep
Exit: (9) 15>4 ? creep
Call: (9) _G9622 is 4+4 ? creep
Exit: (9) 8 is 4+4 ? creep
Call: (9) divisible_ext(8, 15, 4, _G9625) ? creep
Call: (10) 15>8 ? creep
Exit: (10) 15>8 ? creep
Call: (10) _G9625 is 8+4 ? creep
Exit: (10) 12 is 8+4 ? creep
Call: (10) divisible_ext(12, 15, 4, _G9628) ? creep
Call: (11) 15>12 ? creep
Exit: (11) 15>12 ? creep
Call: (11) _G9628 is 12+4 ? creep
Exit: (11) 16 is 12+4 ? creep
Call: (11) divisible_ext(16, 15, 4, _G9631) ? creep
Call: (12) 15>16 ? creep
Fail: (12) 15>16 ? creep
Fail: (11) divisible_ext(16, 15, 4, _G9631) ? creep
Fail: (10) divisible_ext(12, 15, 4, _G9628) ? creep
Fail: (9) divisible_ext(8, 15, 4, _G9625) ? creep
Fail: (8) divisible_ext(4, 15, 4, _G9543) ? creep
Fail: (7) divisible(4, 15, _G9543) ? creep
false.

Why is the base case only being called once?
The base case is
divisible_ext(D,U,D,X) :-
and the other case is
divisible_ext(D,U,S,X) :-
Notice that on the first call
Call: (8) divisible_ext(4, 15, 4, _G9543) ? creep
divisible_ext(D, U, D, X) :- <-- Base case
divisible_ext(D, U, S, X) :- <-- Other case
For the base case D = 4 for both D and
for the other case D = 4 and S = 4
so both predicates can be called.
Notice on the second call
Call: (9) divisible_ext(8, 15, 4, _G9625) ? creep
divisible_ext(D, U, D, X) :- <-- Base case
divisible_ext(D, U, S, X) :- <-- Other case
For the base case D = 8 and D = 4 and
for the other case D = 4 and S = 4
so the base can not be called because the first D is now 8 and second D is 4 which means the unification will not work and thus the predicate can not be called.

Related

Generate lists with independent variables in Prolog

I am having a problem while creating a list which I will the use to fill. I am trying to create it with independent variables, so that I can then unify with a maplist with some other lists.
For this, I did:
length(Subs, Len),
maplist(=([_, _, _]), Subs),
however, this results in this:
Subs = [[_22998, _23020, _23042], [_22998, _23020, _23042], [_22998, _23020, _23042]].
And so, when I try to unify the next way:
maplist(nth1(1), Subs, Com1),
maplist(nth1(2), Subs, Perm_sub),
maplist(nth1(3), Subs, Com3).
with:
Perm_sub = [5, 7, 6],
Com1 = [P23, P34, P36],
Com3 = [1, 3, 2].
It fails, because 5 unifies with _22998, and thus collides with 7. Is there a simple, elegant way of doing what I intend, or do I have to create a new function to handle this, and if so, how do I do the function?
You can create an auxiliary predicate as following:
triple([_, _, _]).
And ask:
?- length(L, 3), maplist(triple, L).
L = [[_2404, _2410, _2416], [_2422, _2428, _2434], [_2440, _2446, _2452]].
Alternatively, you can use a lambda expression as following:
?- length(L, 3), maplist([[_,_,_]]>>true, L).
L = [[_7198, _7204, _7210], [_7276, _7282, _7288], [_7354, _7360, _7366]].
EDIT 10/05/2021
Notice that variables used in a term are shared with their environment (they are "global", not lambda bound) and, consequently, they persist through all calls of maplist. For example, in the following query, variable X is instantiated with 1 and, after that, its value will persist through the next calls.
?- trace, maplist(=(X), [1,Y,1]).
^ Call: (11) apply:maplist(=(_1882), [1, _1892, 1]) ? creep
Call: (12) apply:maplist_([1, _1892, 1], user: =(_1882)) ? creep
Call: (13) _1882=1 ? creep
Exit: (13) 1=1 ? creep
Call: (13) apply:maplist_([_1892, 1], user: =(1)) ? creep
Call: (14) 1=_1892 ? creep
Exit: (14) 1=1 ? creep
Call: (14) apply:maplist_([1], user: =(1)) ? creep
Call: (15) 1=1 ? creep
Exit: (15) 1=1 ? creep
Call: (15) apply:maplist_([], user: =(1)) ? creep
Exit: (15) apply:maplist_([], user: =(1)) ? creep
Exit: (14) apply:maplist_([1], user: =(1)) ? creep
Exit: (13) apply:maplist_([1, 1], user: =(1)) ? creep
Exit: (12) apply:maplist_([1, 1, 1], user: =(1)) ? creep
^ Exit: (11) apply:maplist(user: =(1), [1, 1, 1]) ? creep
X = Y, Y = 1.
On the other hand, variables used as predicate arguments are "local" and their instantiations do not persist from one call to another. For example:
?- [user].
| equal(_X).
| ^Z
% user://1 compiled 0.02 sec, 1 clauses
true.
?- trace, maplist(equal, [1,Y,1]).
^ Call: (11) apply:maplist(equal, [1, _1752, 1]) ? creep
Call: (12) apply:maplist_([1, _1752, 1], user:equal) ? creep
Call: (13) equal(1) ? creep
Exit: (13) equal(1) ? creep
Call: (13) apply:maplist_([_1752, 1], user:equal) ? creep
Call: (14) equal(_1752) ? creep
Exit: (14) equal(_1752) ? creep
Call: (14) apply:maplist_([1], user:equal) ? creep
Call: (15) equal(1) ? creep
Exit: (15) equal(1) ? creep
Call: (15) apply:maplist_([], user:equal) ? creep
Exit: (15) apply:maplist_([], user:equal) ? creep
Exit: (14) apply:maplist_([1], user:equal) ? creep
Exit: (13) apply:maplist_([_1752, 1], user:equal) ? creep
Exit: (12) apply:maplist_([1, _1752, 1], user:equal) ? creep
^ Exit: (11) apply:maplist(user:equal, [1, _1752, 1]) ? creep
true.

Prolog how to add element in a list if is in a list

I m trying to do a list member(member/2) with my own predicate.
starting this example
?-app([a,r,t],[t,s,m,n,a],L3).
L3=[a,t]
I tried to do similar exercises so I did this with prolog:
app([],_,[]).
app([H|T],[H1,T1],[H|L1]):- H is H1, L1 is H,! ,app(T,T1,L1).
app([_H|T],L,L2):- app(T,L,L2).
and all working regular, but the value in a list will be overwritten during the execution, in fact, the trace is :
trace, app([3,2],[3,5],X).
Call: (9) app([3, 2], [3, 5], _7426) ? creep
Call: (10) 3 is 3 ? creep
Exit: (10) 3 is 3 ? creep
Call: (10) _7736 is 3 ? creep
Exit: (10) 3 is 3 ? creep
Call: (10) app([2], 5, 3) ? creep
Call: (11) app([], 5, 3) ? creep
Fail: (11) app([], 5, 3) ? creep
Fail: (10) app([2], 5, 3) ? creep
Fail: (9) app([3, 2], [3, 5], _7426) ? creep
false.
I tried to make a modify on the base case in this way:
app([],_,_N).
but the output is every wrong:
trace, app([3,2],[3,5],X).
Call: (9) app([3, 2], [3, 5], _7426) ? creep
Call: (10) 3 is 3 ? creep
Exit: (10) 3 is 3 ? creep
Call: (10) _7736 is 3 ? creep
Exit: (10) 3 is 3 ? creep
Call: (10) app([2], 5, 3) ? creep
Call: (11) app([], 5, 3) ? creep
Exit: (11) app([], 5, 3) ? creep
Exit: (10) app([2], 5, 3) ? creep
Exit: (9) app([3, 2], [3, 5], [3|3]) ? creep
X = [3|3].
where I m wrong?
I think you're trying to do a sublist/2 predicate:
%! sublist(Sub, List)
% is true if Sub is a list that occurs in
% some position in List
sublist(Sub, List) :-
% first partition off some tail of the list
append(_Prefix, Tail, List),
% then get some prefix of the tail, this is a sublist
append(Sub, _TailTail, Tail).
There's more ways to do this, but I think append/3 is simple to
understand. This is a different problem from member/2, which is finding elements in a list, here our problem is to carve up a list into chunks, hence the very different implementation than you see in member/2. You'll often find in Prolog the first step to a solution is to define the problem well. Good luck in your Prolog learning.

Problem with recursive predicate on Prolog

Goal a(3, X) should return 6. Based on this code. I have converted it to Prolog code but with a problem in a recursive predicate. First two lines are for 0 and 1 to return the same value.
c=1
for i = 2 to n do
if c > i then
c=c-1
else
c=c+1
end if
end for
return c
But at Step 4 it gets the result and then goes back to step 2 and goes back with the iteration to the wrong result. I think there is a unification problem but can't find where.
a(N, N) :- N < 2, !.
a(N, X) :- a(1, 2, N, X).
Step 2.
a(C1, I, N, C1) :- I > N, !.
Step 3.
a(C, I, N, C1) :- C > I, !,
C1 is C - I,
I1 is I + 1,
a(C1, I1, N, C1).
Step 4.
a(C, I, N, C1) :- C =< I, !,
C1 is C + I,
I1 is I + 1,
a(C1, I1, N, C1).
This is the trace.
[trace] ?- a(3, X).
Call: (8) a(3, _1238) ? creep
Call: (9) 3<2 ? creep
Fail: (9) 3<2 ? creep
Redo: (8) a(3, _1238) ? creep
Call: (9) a(1, 2, 3, _1238) ? creep
Call: (10) 2>3 ? creep
Fail: (10) 2>3 ? creep
Redo: (9) a(1, 2, 3, _1238) ? creep
Call: (10) 1>2 ? creep
Fail: (10) 1>2 ? creep
Redo: (9) a(1, 2, 3, _1238) ? creep
Call: (10) 1=<2 ? creep
Exit: (10) 1=<2 ? creep
Call: (10) _1474 is 1+2 ? creep
Exit: (10) 3 is 1+2 ? creep
Call: (10) _1480 is 2+1 ? creep
Exit: (10) 3 is 2+1 ? creep
Call: (10) a(3, 3, 3, 3) ? creep
Call: (11) 3>3 ? creep
Fail: (11) 3>3 ? creep
Redo: (10) a(3, 3, 3, 3) ? creep
Call: (11) 3>3 ? creep
Fail: (11) 3>3 ? creep
Redo: (10) a(3, 3, 3, 3) ? creep
Call: (11) 3=<3 ? creep
Exit: (11) 3=<3 ? creep
Call: (11) _1486 is 3+3 ? creep
Exit: (11) 6 is 3+3 ? creep
Call: (11) _1492 is 3+1 ? creep
Exit: (11) 4 is 3+1 ? creep
Call: (11) a(6, 4, 3, 6) ? creep
Call: (12) 4>3 ? creep
Exit: (12) 4>3 ? creep
Exit: (11) a(6, 4, 3, 6) ? creep !!! SHOULD STOP HERE !!!
Exit: (10) a(3, 3, 3, 3) ? creep
Exit: (9) a(1, 2, 3, 1) ? creep
Exit: (8) a(3, 1) ? creep
X = 1 .
You need another variable. You're "overloading" C1, so it's already instantiated (bound) when you are doing your recursive call and you end up with things like this in the trace (note, using the code you show, I don't get the same trace you do, so you've done something different with your code):
| ?- a(3,X).
1 1 Call: a(3,_23) ?
2 2 Call: 3<2 ?
2 2 Fail: 3<2 ?
2 2 Call: a(1,2,3,_23) ?
3 3 Call: 2>3 ?
3 3 Fail: 2>3 ?
3 3 Call: 1>2 ?
3 3 Fail: 1>2 ?
3 3 Call: 1=<2 ?
3 3 Exit: 1=<2 ?
4 3 Call: _23 is 1+2 ?
4 3 Exit: 3 is 1+2 ?
5 3 Call: _174 is 2+1 ?
5 3 Exit: 3 is 2+1 ?
6 3 Call: a(3,3,3,3) ?
7 4 Call: 3>3 ?
7 4 Fail: 3>3 ?
7 4 Call: 3>3 ?
7 4 Fail: 3>3 ?
7 4 Call: 3=<3 ?
7 4 Exit: 3=<3 ?
8 4 Call: 3 is 3+3 ?
8 4 Fail: 3 is 3+3 ? <--- FAILS HERE: DUE TO C1 ALREADY BOUND
3 cannot be 3+3 !
6 3 Fail: a(3,3,3,3) ?
2 2 Fail: a(1,2,3,_23) ?
1 1 Fail: a(3,_23) ?
(1 ms) no
So here's the correction with an additional variable:
a(C, I, N, C1) :- C > I, !,
C2 is C - I,
I1 is I + 1,
a(C2, I1, N, C1).
a(C, I, N, C1) :- C =< I, !,
C2 is C + I,
I1 is I + 1,
a(C2, I1, N, C1).
Then you get:
| ?- a(3,X).
X = 6
(1 ms) yes
| ?-
As an aside, don't be so quick to sprinkle cuts throughout your code. Get it all working first without them. Then put them in very intentionally to prune decision branches. They sometimes prune out paths that you really want and lead to undesirable results.

Prolog checking the same fact twice

This is the knowledge database
student(jack,100,21,m).
takes(100,cs01).
takes(100,cs02).
takes(100,cs03).
teaches(doe,cs01).
course(cs01,ai).
course(cs02,cpp).
course(cs03,java).
isTaughtBy(Sname,Lname) :-
teaches(Lname,Mcode),
student(Sname,Scode,_,_),
takes(Scode,Mcode).
When running isTaughtBy(jack,doe) it returns true (like its supposed to) and false (for some reason, probably because jack takes multiple modules).
This is the trace:
[trace] ?- isTaughtBy(jack,doe).
Call: (8) isTaughtBy(jack, doe) ? creep
Call: (9) teaches(doe, _18526) ? creep
Exit: (9) teaches(doe, cs01) ? creep
Call: (9) student(jack, _18526, _18528, _18530) ? creep
Exit: (9) student(jack, 100, 21, m) ? creep
Call: (9) takes(100, cs01) ? creep
Exit: (9) takes(100, cs01) ? creep
Exit: (8) isTaughtBy(jack, doe) ? creep
true ;
Redo: (9) takes(100, cs01) ? creep
Fail: (9) takes(100, cs01) ? creep
Fail: (8) isTaughtBy(jack, doe) ? creep
false.
Why is it redoing takes(100,cs01) if it was already checked above? Why is it returning false even though its clearly defined in the database? What am i not understanding here? I just want it to return true or false if a student is taught by a lecturer on any of the modules they are taking.

Maximum Subarray (Kadane's algorithm) - Tail recursion

i am trying to implement Kadane's Algorithm in Prolog.
One of the requirements is a tail call (recursion).
I have tried many possibilities but without success.
Here is my code:
max_sum(L, S) :-
S is 0,
H is 0,
max_sum(L, H, S).
max_sum([], S, S).
max_sum([X | L], H, S) :-
( H + X < 0 -> NewH is 0; NewH is H + X),
( S < H + X -> NewS is NewH; NewS is S),
length(L, N),
( N < 1 -> max_sum(L, NewS, NewS); max_sum(L, NewH, NewS)).
NewH, NewS are temp values (we cant assign a value twice in Prolog right?).
Can i ask for a hint?
Edit:
[trace] ?- max_sum([1, 2, 3], S).
Call: (7) max_sum([1, 2, 3], _G8907) ? creep
Call: (8) _G8907 is 0 ? creep
Exit: (8) 0 is 0 ? creep
Call: (8) _G8991 is 0 ? creep
Exit: (8) 0 is 0 ? creep
Call: (8) max_sum([1, 2, 3], 0, 0) ? creep
Call: (9) 0+1<0 ? creep
Fail: (9) 0+1<0 ? creep
Redo: (8) max_sum([1, 2, 3], 0, 0) ? creep
Call: (9) _G8994 is 0+1 ? creep
Exit: (9) 1 is 0+1 ? creep
Call: (9) 0<0+1 ? creep
Exit: (9) 0<0+1 ? creep
Call: (9) _G8997 is 1 ? creep
Exit: (9) 1 is 1 ? creep
Call: (9) length([2, 3], _G8998) ? creep
Exit: (9) length([2, 3], 2) ? creep
Call: (9) 2<1 ? creep
Fail: (9) 2<1 ? creep
Redo: (8) max_sum([1, 2, 3], 0, 0) ? creep
Call: (9) max_sum([2, 3], 1, 1) ? creep
Call: (10) 1+2<0 ? creep
Fail: (10) 1+2<0 ? creep
Redo: (9) max_sum([2, 3], 1, 1) ? creep
Call: (10) _G9000 is 1+2 ? creep
Exit: (10) 3 is 1+2 ? creep
Call: (10) 1<1+2 ? creep
Exit: (10) 1<1+2 ? creep
Call: (10) _G9003 is 3 ? creep
Exit: (10) 3 is 3 ? creep
Call: (10) length([3], _G9004) ? creep
Exit: (10) length([3], 1) ? creep
Call: (10) 1<1 ? creep
Fail: (10) 1<1 ? creep
Redo: (9) max_sum([2, 3], 1, 1) ? creep
Call: (10) max_sum([3], 3, 3) ? creep
Call: (11) 3+3<0 ? creep
Fail: (11) 3+3<0 ? creep
Redo: (10) max_sum([3], 3, 3) ? creep
Call: (11) _G9006 is 3+3 ? creep
Exit: (11) 6 is 3+3 ? creep
Call: (11) 3<3+3 ? creep
Exit: (11) 3<3+3 ? creep
Call: (11) _G9009 is 6 ? creep
Exit: (11) 6 is 6 ? creep
Call: (11) length([], _G9010) ? creep
Exit: (11) length([], 0) ? creep
Call: (11) 0<1 ? creep
Exit: (11) 0<1 ? creep
Call: (11) max_sum([], 6, 6) ? creep
Exit: (11) max_sum([], 6, 6) ? creep
Exit: (10) max_sum([3], 3, 3) ? creep
Exit: (9) max_sum([2, 3], 1, 1) ? creep
Exit: (8) max_sum([1, 2, 3], 0, 0) ? creep
Exit: (7) max_sum([1, 2, 3], 0) ? creep
In Call(11) i have a good result (6) from this simple example. How can I end the function at this point without returning? It is my problem.
Result from this code is S = 0, not S = 6.
Final edit (working code):
max_sum(L, S) :-
max_sum(L, 0, 0, S).
max_sum([], _, S, S).
max_sum([X | L], H, F, S) :-
NewH is max(0, H + X),
(F < H + X -> NewF is NewH; NewF is F),
max_sum(L, NewH, NewF, S).
Where:
S - final result,
F - maximum_so_far,
H - maximum_ending_here,
X - head of list,
L - list,
NewH, NewF - temp values.
Thanks for the help :)
This question is, in fact, a duplicate of
"Finding the maximum sublist in Prolog".
There is a bounty is offered for it, so it cannot be flagged as a duplicate.
I propose using my previous solution—it is based on clpfd and runs with SWI-Prolog.
I propose a slightly altered version of the solution proposed by #repeat:
:- use_module(library(clpfd)).
zs_max([Z|Zs], MSF) :-
zs_max_(Zs, Z, Z, MSF).
zs_max_([], _, MSF, MSF).
zs_max_([Z|Zs], MEH0, MSF0, MSF) :-
max(Z, MEH0+Z) #= MEH1,
max(MSF0, MEH1) #= MSF1,
zs_max_(Zs, MEH1, MSF1, MSF).
First, the sample queries from the original solution that yield the same results:
?- zs_max([-2,1,-3,4,-1,2,1,-5,4], Max).
Max = 6
?- zs_max([-2,3,4,-5,8,-12,100,-101,7], Max).
Max = 100
However this version is more general, in that it works with arbitrary values (as suggested by #false in the comment to solution). This is accomplished by starting with the value of the first element of the list instead of 0. Thus the following query yields a different result:
?- zs_max([-2,-3,-4], X).
X = -2
?- zs_maxmum([-2,-3,-4], X).
X = 0
Another difference is that the empty list has no solution:
?- zs_max([], X).
no
?- zs_maxmum([], X).
X = 0
I think this behaviour is more reasonable, as the empty list has no sublist and hence no sums of sublists from which to choose a maximum. However, if desired, a special case for the empty list can be easily added:
zs_max([], replaceThisWithAReasonableValue).
the standard way is to add an output parameter, that gets unified when the recursion stops. Something like
max_sum(L, S) :-
max_sum(L, 0, 0, S).
max_sum([], _, S, S).
...
Then, your code is way more complex than needed: both versions listed on Wikipedia don't require any test, or length/2 computation.
Try to simplify it leaving just the computation (you can use for instance Max_ending_here is max(0, H + X), and the tail recursive call.

Resources