Prolog stucks after giving the result - prolog

So I have this knowledge base and I am trying to achieve the goals in the code given as comments.
%format of foo: foo(Tag,NumList)
foo(a, [2, 4]).
foo(b,[2, 8, 8, 6,2]).
foo(c,[4, 8, 8, 8, 7]).
foo(d,[7, 8, 8, 2]).
foo(e,[5, 8, 9, 6]).
foo(f,[2, 5]).
foo(g,[2, 6]).
foo(h, [2, 8, 2]).
foo(i, [2, 8, 8, 2]).
foo(j, [2, 3]).
However there is a problem with the goo part. When I only give Total_num to goo and get the unified results for Foo_list, it gives the results but after that it just gets stuck. Nothing works and I have to close the interpreter all the time.
I tried putting cuts to goo helpers but nothing works. Also when I change the order of predicates in goo(putting goo_ordered in front), it doesn't give the list and just gets stuck. How can I fix this problem? What causes it?
Thank you
%returns the sum of the numbers the NumList
foo_sum(Tag,SUM):- foo(Tag,List),foo_sum_helper(List,SUM).
foo_sum_helper([],0).
foo_sum_helper([H|T],Result):- foo_sum_helper(T,Prev_result), Result is H + Prev_result.
%foo diff find the last number in the list.
%It should remain the if it is less than or equal to four, otherwise substract 8 from it
foo_diff(Tag,Diff):- foo(Tag,List),foo_diff_helper(List,Diff).
foo_diff_helper([Last],Result):- Last =< 4, Result is Last,!.
foo_diff_helper([Last],Result):- Last > 4, Result is Last - 4,!.
foo_diff_helper([_,X|T],Result):- foo_diff_helper([X|T], Result).
%goo takes a list of foo's and a number that represents the total number of each foo_sum of foo's.
%Total of foo_diff must be 0
%Also the list of foo's must be in the ascending order.(foo_sum of the first foo in the list is the least one.)
goo(Foo_list,Total_num):- goo_sum(Foo_List,Total_num),goo_diff(Foo_list,0),goo_ordered(Foo_list).
goo_ordered([]).
goo_ordered([_]).
goo_ordered([X,Y|Z]):- foo_sum(X,NUMX),foo_sum(Y,NUMY),NUMX =< NUMY, goo_ordered([Y|Z]).
goo_sum([X],RESULT):- foo_sum(X,RESULT).
goo_sum([H|T],RESULT):- goo_sum(T,PREV_RESULT),foo_sum(H,NUMH), RESULT is NUMH + PREV_RESULT.
goo_diff([X],RESULT):- foo_diff(X,RESULT).
goo_diff([H|T],RESULT):- goo_diff(T,PREV_RESULT),foo_diff(H,HDIFF), RESULT is HDIFF + PREV_RESULT.

What causes it?
Assuming you mean the looping of goo_sum(X, 20):
For the query I get quite a lot of answers. Actually, too much for me. So I will instead consider
?- goo_sum(X, 20), false.
which loops. The A reason is the following very compact failure-slice
goo_sum([X],RESULT):- false, foo_sum(X,RESULT).
goo_sum([H|T],RESULT):-
goo_sum(T,PREV_RESULT), false,
foo_sum(H,NUMH), RESULT is NUMH + PREV_RESULT.
You need to fix the remaining part somehow or the loop will remain.
BTW, using names as foo and goo is not a very good idea. I still do not understand your program and so do you, I presume.
I'd rather stick to smaller programs first. Also consider to use clpfd in place of the moded arithmetic via (is)/2. Here is such a suggested improvement—for a question of your colleague presumably.
And: You got some warnings by the system about a singleton variable, you need to fix that anyway. That is s/Foo_List/Foo_list/

Related

List manipulation with prolog

I am trying to create a query that gives back the following:
sky([1,2,3,4,5,6],X).
X = [1,3,5,2,6,4]
That is, it takes out every other element of a list, and does the same on the remaining list and puts everything together.
This is my code so far.
sky([X|Y], Skied):-
split([X|Y],Z1),
split(X,Z2),
sky(Z2,Z3),
append(Z1,Z3,Skied).
sky([],[]).
split([X,_|T], [X|R]):-
split(T,R).
split([X|[]], [X]).
split([],[]).
Can someone explaint o me why it wont work and the process behind it, like a visual guide. Thanks!
Your code is almost right, instead of split(X,Z2) you need to write split(Y,Z2). That's because X is a single element and split(X,Z2) will return [X], which if I understood correctly isn't what you want. You need to write split(Y,Z2) to take the even elements (or in your description every other element) and call sky(Y,Z3) to do the same recursively. So the new version is:
sky([X|Y], Skied):-
split([X|Y],Z1),
split(Y,Z2),
sky(Z2,Z3),
append(Z1,Z3,Skied).
sky([],[]).
split([X,_|T], [X|R]):-
split(T,R).
split([X|[]], [X]).
split([],[]).
Some examples and output:
?- sky([1,2,3,4,5,6],X).
X = [1, 3, 5, 2, 6, 4] ;
false.
?- sky([1,2,3,4,5,6,7,8,9],X).
X = [1, 3, 5, 7, 9, 2, 6, 4, 8] ;
false.

prolog list keeps expanding when semi colon is pressed

Hi I am creating a predicate list from, which if used gives you the numbers between a certain range. So say for instance
list_from(1,5,X).
would give you
X=[1,2,3,4,5].
However I got my predicate to work, but the list just keeps expanding, so it keeps increasing my one and I do not want it to. This is what is happening.
?- list_from(1,7,X).
X = [1, 2, 3, 4, 5, 6, 7] ;
X = [1, 2, 3, 4, 5, 6, 7, 8] ;
X = [1, 2, 3, 4, 5, 6, 7, 8, 9] ;
X = [1, 2, 3, 4, 5, 6, 7, 8, 9|...] ;
X = [1, 2, 3, 4, 5, 6, 7, 8, 9|...]
How do I get this to stop?
Here is my code
list_from(M,N,[]):- M > N.
list_from(M,N,[M|T]):- Mplusone is M + 1, list_from(Mplusone,N,T).
if I remove Mplusone and just M instead I get an error "Out of global stack"
Your two clauses are not mutually exclusive. You have a "guard" in the first clause saying that M > N, but you don't have the opposite condition, M =< N, in the second clause. If you trace the execution you should get an idea of what happens with your current definition.
You might also try to look at the definition of numlist/3 in SWI-Prolog's library(lists). It takes a different approach: first, make sure that the arguments make sense; then, under the condition that the initial Low is indeed lower than High (and both are integers), generate a list.
Semicolon means that you want Prolog to show you more options (that you are not satisfied with the answer). A full stop '.' will stop Prolog from providing you with alternatives.
You could also invoke list_from/3 using once/1. (Credit to #mat)

Issue with output in Prolog

I recently wanted to experiment with Prolog to understand how the process of unification works so I wrote the following code to return the nth element from a list.
getfromarray([X|_],1,X).
getfromarray(A,N,E):-
N > 1,
A = [_|Y],
N1 is N-1,
getfromarray(Y,N1,E).
However, upon entering the input to the program as
getfromarray(A,3,E), it returns :-
A = [_G5129, _G5132, E|_G5136]
I understand that since i wrote the rule A = [_|Y] , A is being unified to satisfy the conditions of the rules in the program hence A is being displayed in this format. However, I don't understand why E is not being unified with the value in the array. I did read through the basics of unification in Prolog and I understand that while the answer is not wrong, it does not do what it is intended to do. Can someone suggest a topic in unification I might have missed upon which might help me solve this minor issue?
EDIT:
When I passed a list as a parameter to the program, it gave the associated value of E in the list.However, when I unified a variable A with a list and passed A as a parameter to the program, It is displaying the same output as i mentioned above.
5 ?- getfromarray([1,2,5,4,5],3,E).
E = 5 .
6 ?- A = [1,2,3,4,5].
A = [1, 2, 3, 4, 5].
7 ?- getfromarray(A,3,E).
A = [_G576, _G579, E|_G583] .
8 ?-
Prolog doesn't store your list A, therefore A is uninstantiate.
A = [1, 2, 3, 4, 5].
getfromarray(A,3,E).
This is like just calling :
getfromarray(A,3,E).
Try this in stead :
A = [1, 2, 3, 4, 5], getfromarray(A,3,E).

Please explain the cut in the Bubblesort Prolog program?

I'm currently working trough the Bratko Prolog book and I am looking at the bubble-sort Program. I can't seem to figure out why the cut(!) is necessary. Say the cut isn't there, and Prolog would backtrack, how could it possibly find bad answers? Because if I leave the cut out of it, Prolog begins by giving me the correct answer but then also gives alternative bad answers.
As I see it, how can swap ever return a non sorted list? And how is it possible that a non sorted list ever hits the goal bubblesort(Sorted, Sorted).
Unless of course the first List is also being changed... Can't get my head around it.
Prolog BubbleSort program:
gt(X,Y) :- X > Y.
bubblesort(List, Sorted) :-
swap(List, List1), !, % A useful swap in List?
bubblesort(List1, Sorted).
bubblesort(Sorted, Sorted). % Otherwise list is already sorted
swap([X,Y|Rest], [Y,X|Rest]) :- % Swap first two elements
gt(X,Y).
swap([Z|Rest], [Z|Rest1]) :- % Swap elements in tail
swap(Rest, Rest1).
Leaving the cut of out it gives me:
?- bubblesort([5,7,3,6,8,9,2,6], Sorted).
Sorted = [2, 3, 5, 6, 6, 7, 8, 9] ;
Sorted = [2, 3, 5, 6, 7, 6, 8, 9] ;
Sorted = [2, 3, 5, 6, 7, 8, 6, 9] ;
Sorted = [2, 3, 5, 6, 7, 8, 9, 6] ;
I think that somehow I get it, but I am not sure. Could it be that at a certain moment, it backtracks over swap(List, List1) going to the second bubble-sort predicate and hitting the goal, meaning the two lists Sorted are equal?
In English, does this mean that bubble-sort needs to continue doing swaps until no more swaps are possible, but then needs to terminate? Or does it mean that every-time a successful swap has been done, there's no use backtracking over that success?
There are several possibilities to make the goal swap(List, List1) fail. Either List is a list of length 0 or 1 ; or it does not contain two immediately succeeding elements where the second is smaller than the first.
The cut is placed in such a manner that it both cuts swap/2 and the alternative of bubblesort/2.
This is a good example, where a "deep cut" (cutting deep into swap/2) still works somewhat nicely. However, such situations are very rare. Most of the time, the cut cuts too much. The largest majority of such programs is very brittle to use, even more so, if the second argument is given already. They are often not steadfast.
Ah, I almost missed it: Even in this program, we have bubblesort(nonlist,L) succeeding, or bubblesort([1|nonlist],L) which probably is not intended and leads to subtle programming errors.
There is also another reason why this program does not present the ideal logic programming style: The second rule of bubblesort/2 when read alone says: Everything is a sorted list`. To understand this, we have to read both rules at the same time and narrow it down to Everything but ....
In English, does this mean that bubble-sort needs to continue doing swaps until no more swaps are possible, but then needs to terminate? Or does it mean that every-time a successful swap has been done, there's no use backtracking over that success?
It is the first procedural meaning that applies here. And certainly, backtracking over the success to the second clause of bubblesort/2 would be an error.
A further quite unintuitive detail which is not specific to the cut, is that in addition to numbers, the program also succeeds for expressions like bubblesort([1,1+1],L) which again might lead to subtle differences.
I just want to add that if-then-else is a far more appropriate language construct than !/0 to express the intention (and I know you did not choose !/0 on your own here):
bubblesort(List0, List) :-
( swap(List0, List1) ->
bubblesort(List1, List)
; List0 = List
).
You can change the -> to *-> to see alternative solutions of swap/2 as well, i.e., if you change this to:
bubblesort(List0, List) :-
( swap(List0, List1) *->
bubblesort(List1, List)
; List0 = List
).
Then you get for example:
?- bubblesort([5,7,3,6,8,9,2,6], Ascending).
Ascending = [2, 3, 5, 6, 6, 7, 8, 9] ;
Ascending = [2, 3, 5, 6, 6, 7, 8, 9] ;
Ascending = [2, 3, 5, 6, 6, 7, 8, 9] .
As you see, all of these lists are non-decreasing, as you already expected.

Prolog decomposition returning a period

I have a predicate that decomposes an expression and I am having results that I dont understand when I trace through it.
My predicate is as below
calc(R,Expr) :- Expr =..[Op,H,T].
So when I have an expression like [1,1], the Op is actually a period. Any idea why?
It's because the form [Head|Tail] is just syntactic sugar for '.'(Head, Tail) (everything is a term and lists are no exception). Normally, for the list made of 1, 2, 3 and 4, you'd have to write
'.'(1, '.'(2, '.'(3, '.'(4, [])))).
As you can see, that's not very practical and instead we use the shortcut:
[1|[2|[3|[4|[]]]]]
And this shortcut has a shortcut:
[1, 2, 3, 4]
And you can mix those as you wish:
[1, 2|[3, 4]]
That is handy when you want to specify some elements and then let the tail free:
[1, 2|A]
BTW, you can see that for yourself by using write_canonical/1:
?- write_canonical([1, 2, 3, 4]).
'.'(1,'.'(2,'.'(3,'.'(4,[]))))
true.
Hope it helped

Resources