Prolog decomposition returning a period - prolog

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

Related

Prolog - Recursive append to list returning false

Title says it all, but here we are again. Trying to append recursively to a list in Prolog, and while I have previously gotten it to work by having "temporary buffers" (via nb_setval/nb_getval) I'd like to learn how to, in a slightly more appropriate way, recursively append to lists.
I've understood Prolog works all around bindings and once something is bound it's difficult to manipulate it, so initially I sat with this, but I've understood why that does not quite work:
recursiveAppend([], _).
recursiveAppend([H|T], Output):-
append(H, [], Output),
recursiveAppend(T, Output).
That made me change the code and go to the following:
recursiveAppend([], _).
recursiveAppend([H|T], Output):-
append(H, Output, NewOutput),
recursiveAppend(T, NewOutput).
Which I had hoped would work, as it made sense to myself and apparently to others while scouring other StackOverflow questions as well. Unfortunately, calling this predicate in SWI-Prolog only returns false.
?- recursiveAppend([1, 2, 3, 4, 5], L1). false
Expected/desired result would, in this case, be:
?- recursiveAppend([1, 2, 3, 4, 5], L1). L1 = [1, 2, 3, 4, 5].
For the sake of clarification, the runtime of the program should look something like this if "fleshed out":
recursiveAppend([H|T], Output):-
% H is 1, Output is []
append(H, Output, NewOutput),
% NewOutput is [1]
recursiveAppend(T, NewOutput).
recursiveAppend([H|T], Output):-
% H is 2, Output is [1]
append(H, Output, NewOutput),
% NewOutput is [1, 2]
recursiveAppend(T, NewOutput).
recursiveAppend([H|T], Output):-
% H is 3, Output is [1, 2]
append(H, Output, NewOutput),
% NewOutput is [1, 2, 3]
recursiveAppend(T, NewOutput).
recursiveAppend([H|T], Output):-
% H is 4, Output is [1, 2, 3]
append(H, Output, NewOutput),
% NewOutput is [1, 2, 3, 4]
recursiveAppend(T, NewOutput).
recursiveAppend([H|T], Output):-
% H is 5, Output is [1, 2, 3, 4]
append(H, Output, NewOutput),
% NewOutput is [1, 2, 3, 4, 5]
recursiveAppend(T, NewOutput).
recursiveAppend([], _). % First argument (list) is empty, and the second argument (list) has been populated (with [1, 2, 3, 4, 5]), program done.
Any and all help is appreciated, even though this question has probably been asked a million times before!
"Recursive append" is not something that often makes sense in Prolog. The question should include information about what problem you are trying to solve. Currently it is not about that; it is about how you are trying to solve your problem. That "how" is "recursive append", but this is almost certainly not how you should really solve that problem. We could offer better help if we knew what the problem was, not how you think you want to solve it.
Taking the example from the question and the solution from https://stackoverflow.com/a/64092447/4391743:
?- recursiveAppend([1, 2, 3], Ys).
Ys = [1, 2, 3].
?- recursiveAppend(Xs, [1, 2, 3]).
Xs = [1, 2, 3] ;
% nontermination after first answer
?- recursiveAppend([1, 2, X], [A, B, 3]).
X = 3,
A = 1,
B = 2.
?- recursiveAppend([1, 2 | Rest], [A, B, 3, 4]).
Rest = [3, 4],
A = 1,
B = 2 ;
% nontermination after first answer
If this is what you want, then what you seem to want is a "list copy" predicate. Here's a shorter, faster, more complete one:
list_copy([], []).
list_copy([X | Xs], [X | Ys]) :-
list_copy(Xs, Ys).
This doesn't have the non-termination issues that the above predicate has:
?- list_copy([1, 2, 3], Ys).
Ys = [1, 2, 3].
?- list_copy(Xs, [1, 2, 3]).
Xs = [1, 2, 3].
?- list_copy([1, 2, X], [A, B, 3]).
X = 3,
A = 1,
B = 2.
?- list_copy([1, 2 | Rest], [A, B, 3, 4]).
Rest = [3, 4],
A = 1,
B = 2.
If one of the arguments is a list and the other is a variable, a new list structure will be built up and bound to this variable.
But... why do you need a new list structure at all? In pure Prolog you can't tell whether two terms are the same (i.e., sharing the same memory location) or "just" structurally equal. Neither do (or should) you usually care. (There are uses for knowledge about sharing, and about explicit copying, in non-pure Prolog, but again we don't know what you're trying to do.)
So if we can't tell whether a "copy" is indeed a copy or just "an equal term", then we don't need to copy at all. We can get the exact same behavior as above with just unification:
?- [1, 2, 3] = Ys.
Ys = [1, 2, 3].
?- Xs = [1, 2, 3].
Xs = [1, 2, 3].
?- [1, 2, X] = [A, B, 3].
X = 3,
A = 1,
B = 2.
?- [1, 2 | Rest] = [A, B, 3, 4].
Rest = [3, 4],
A = 1,
B = 2.
No copying and certainly no "recursive append" is needed to achieve unification, Prolog knows how to do unification for you.
If this is not what you want, please tell us what the actual problem is. "Recursive append" is almost certainly not it.
Prolog is a different programming paradigm. It requires you to "forget" all you know about programming and learn with an open mind. Don't try to learn Prolog while using "ordinary" variables and reaffecting different values, Prolog variables has only one value or none. They may take different values only on backtracking, and trying to find another set of values to all variables in your program that satisfies all the given predicates.
Suggest you to read books like "learn Prolog Now". Numerous tutorials from state universities are available free on the internet.
Based on your latest edit giving an example to Calling recursiveAppend, here's a code conform with the example.
recursiveAppend(X, Y) :- recursiveAppend(X, [], Y).
recursiveAppend([], X, X).
recursiveAppend([H|T], Current, Output):-
append(Current, [H], NewTemp),
recursiveAppend(T, NewTemp, Output).
Your earlier codes returned false because append expects lists as arguments. So appending an integer (item of input list) will Always fail. I created a version recursiveAppend/3 to accumulate current list in the second arg. At the end of the list, the current list becomes the final output. Will you test it further with more examples and tell us if it is working as required.

Prolog doesn't return a value

I have the following code:
pair_list([X,Y],[[X,Y]]).
pair_list([E,Z|X],[K|Y]):- [E,Z]==K, pair_list(X,Y).
When I run it, it gives correct output for
?- pair_list([1, 2, 3, 4, 5, 6], [[1, 2], [3, 4], [5, 6]]).
true ;
but when I run
?- pair_list([1,2, 3, 4, 5, 6], X).
I just get false.
My question is why don't I get X=[[1, 2], [3, 4], [5, 6]]
You are almost there: all you need to do is moving [E,Z] into the head, eliminating K:
pair_list([X,Y],[[X,Y]]).
pair_list([E,Z|X],[[E,Z]|Y]) :- pair_list(X,Y).
Demo 1.
Note that the base clause can be replaced with one based on empty lists:
pair_list([], []).
pair_list([E,Z|X],[[E,Z]|Y]) :- pair_list(X,Y).
Demo 2.
Also note that your program is not going to work with a list that has an odd number of items. In order to fix this, add a separate base clause that handles a list with a single item either by dropping the item, making a pair with some fixed atom, or doing something else that you find useful in this case.

Prolog - sort sublists of a list

I want to sort the sublists of a list which contains integers eliminating the duplicates. Example:
[1, 2, [4, 1, 4], 3, 6, [7, 10, 1, 3, 9], 5, [1, 1, 1], 7]
=>>>
[1, 2, [1, 4], 3, 6, [1, 3, 7, 9, 10], 5, [1], 7].
I know that i have to work with functor s(but i didn't really get it).
Here is my code : (the (insert+sorting) function works in a simple list of integers,but don't work here. i'm getting red false everytime)
insert(E,[],[E]).
insert(E,[H|T],[H|L]):-
E>H,
insert(E,T,L).
insert(E,[H|T],[H|T]):-
E=H,
!.
insert(E,[H|T],[E|[H|T]]):-
E<H,
!.
sort([],[]).
sort([i(H)|T],L):-
sort(T,L1),
insert(i(H),L1,L).
You could try a solution like this, it uses the the sort/2 predicate to sort sublists:
sort_sublists([], []).
sort_sublists([X|Xs], List) :-
(integer(X) ->
List = [X | List1]
;
sort(X, Sorted),
List = [Sorted | List1]
),
sort_sublists(Xs, List1).
Example call:
?- set_prolog_flag(answer_write_options,[max_depth(0)]).
true.
?- sort_sublists([1, 2, [4, 1, 4], 3, 6, [7, 10, 1, 3, 9], 5, [1, 1, 1], 7], X).
X = [1,2,[1,4],3,6,[1,3,7,9,10],5,[1],7].
#Eduard Adrian it's hard to answer in comments, so first thing you need to do is to remove duplicates from the nested lists.
Here i tried that and you can see different cases that you need to handle. One example:(Head of your list can be a list but it's tail will be empty this happends if last element of your list is a list) in that case you need to define another predicate which will match your recursive call.
Once you have removed duplicates you can use simple sorting algorithm but you have to check if the head is a list then you sort innner list first and place it to the same place otherwise call sort predicate.
As you asked how check if an element is_list or integer, for that you can always use built-in because those predicates you can't write by yourself.

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.

Resources