Prolog Sorting List By Rule Position - prolog

I am new to Prolog and for the following program:
place(Store,2,a).
place(Store,1,b).
place(Store,3,d).
place(Store,4,c).
placeSort(S,List):- findall(L,place(S,N,L),List).
output: List = [a, b, d, c].
By using placeSort(S,List) , I can find all the elements(a,b,c,d) that contains S (Store).
However what I want to achieve here is to sort the Position of a,b,c,d by using N, however I dont know how to do so as using sort will just sort it out by alphabetical order
placeSort(S,NewList):- findall(L,place(S,N,L),List),sort(List,NewList).
output: List = [a, b, c, d].
what I want to achieve : List = [b,a,d,c]
**I know by using placeSort(S,NewList):- findall([N,L],place(S,N,L),List),sort(List,NewList).
it will return a list of lists sorted by numbers.
output : List = [[1, b], [2, a], [3, d], [4, c]].
but im not sure how to take away the numbers and just take the alphabets instead.
Any help would be greatly appreciated.

SWI-Prolog offers the interesting builtin order_by/2, filling the gap traditional Prolog suffers when compared to SQL, with library(solutionsequences):
?- order_by([asc(X)],place(P,X,W)).
X = 1,
W = b ;
X = 2,
W = a ;
...
So you can avoid full list construction.

The easiest way to do this is to use setof/3 (which sorts by term) and pick a term form that works for you on your sort. In this case, you can collect terms of the form N-X where they satisfy, place(_, N, X):
setof(N-X, place(S,N,X), OrderedList). % Assuming `S` is bound
This will result in:
OrderedList = [1-b, 2-a, 3-d, 4-c]
Then you can use maplist/3 to get your list by defining a simple mapping:
foo(_-X, X).
maplist(foo, OrderedList, List).
This will then give you just the elements you want.
Your complete predicate would look like:
foo(_-X, X).
placeSort(S, List) :-
setof(N-X, place(S,N,X), OrderedList),
maplist(foo, OrderedList, List).
Obviously, you'd choose sensible names for your facts, predicates, and variables. My names (foo, List, OrderedList, S, N, X) are not sufficient, in my opinion, for an application but I am not familiar with your actual problem domain, so this is just for illustration purposes.
As an aside, note that in your facts Store is a variable, so that's not particularly meaningful in the facts. I kept your use of S in your predicate, but it's unclear to me how you really intend to use it.

Related

findall/3 creates new, unrelated variables in its resulting list

?- permutation([A,B,C],Z).
Z = [A, B, C] ;
Z = [A, C, B] ;
Z = [B, A, C] ;
Z = [B, C, A] ;
Z = [C, A, B] ;
Z = [C, B, A] ;
false.
Makes sense. I can work on a permutation of [A,B,C] and that permutation contains the same elements as in [A,B,C], so everything I do to those elements will apply to my original list.
Now:
?- findall(X, permutation([A,B,C], X), Z).
Z = [[_G1577, _G1580, _G1583], [_G1565, _G1568, _G1571], [_G1553, _G1556, _G1559], [_G1541, _G1544, _G1547], [_G1529, _G1532, _G1535], [_G1517, _G1520, _G1523]].
Why?? Why is findall/3 giving me lists which contain completely unrelated variables, instead of A,B,C? The lists in Z are not even related to each other, so really the result I get is just 6 random lists of length 3, which is totally not what I queried.
With this behavior we get ridiculous results like this:
?- findall(X, permutation([A,B,C],X), Z), A = 1.
A = 1,
Z = [[_G1669, _G1672, _G1675], [_G1657, _G1660, _G1663], [_G1645, _G1648, _G1651], [_G1633, _G1636, _G1639], [_G1621, _G1624, _G1627], [_G1609, _G1612, _G1615]].
Which makes no sense from a logical standpoint.
I understand that findall/3 is not really a relational, pure logic predicate but I don't see how this justifies the behavior shown here.
My questions are therefore:
Why was this behavior chosen for the predicate?
Are there common situations where this behavior is actually preferable to the one I want?
How to implement a version of findall/3 with the behavior I want?
Why was this behavior chosen for the predicate?
findall/3 is a highly primitive built-in predicate that is relatively easy to implement and that does not address all the nitty-gritty details you are interested in. At least it is reentrant - thus can be used recursively.
Historically, DEC10 Prolog did not document findall/3. That is, neither in 1978 nor 1984. The 1984 version did however provide setof/3 which internally uses a findall-like predicate. Implementing it in ISO-Prolog (without findall/3) is relatively tricky since you have to handle errors and nesting. Many implementations rely on implementation specific primitives.
Are there common situations where this behavior is actually preferable to the one I want?
Findall succeeds if there is no solution whereas both setof/3 and bagof/3 simply fail. This might be a reason to prefer it. At least some more sophisticated constructs than those are needed which are most probably built based on findall.
It gets pretty messy in the presence of constraints. In fact, it is so messy, that as of the current point in time I am still unaware of an implementation that would deal in a reasonable manner with clpfd-constraints in this very situation. Think of:
?- findall(A, (A in 1..3 ; A in 5..7), As).
Here, SWI copies constraints, where SICStus does not copy them permitting you thus to use it as building-block for a more sophisticated implementation.
How to implement a version of findall/3 with the behavior I want?
First, consider setof/3 and bagof/3 (here). Maybe you are happy with them already - as long as no constraints are involved...
A solution to your last question.
?- setof(X,permutation([A,B,C],X),Z).
Z = [[A, B, C], [A, C, B], [B, A, C], [B, C, A], [C, A, B], [C, B, A]].
If we look at the description of findall at sicstus we see
findall(?Template,:Goal,?Bag) ISO
Bag is a list of instances of Template in all proofs of Goal found by Prolog. The order of the list corresponds to the order in which the proofs are found. The list may be empty and all variables are taken as being existentially quantified. This means that each invocation of findall/3 succeeds exactly once, and that no variables in Goal get bound. Avoiding the management of universally quantified variables can save considerable time and space.
So I guess the existential quantifying creates this unwanted behaviour of findall.
?- findall(X, permutation([A,B,C],X), Z), A = 1.
In this query Prolog will find all permutation of the elements on the list [A,B,C], but since Prolog can not instantiate the variables A, B, C, the result will be this that you are getting, the anonymous variable:
Z = [[_G1669, _G1672, _G1675], [_G1657, _G1660, _G1663], [_G1645, _G1648, _G1651], [_G1633, _G1636, _G1639], [_G1621, _G1624, _G1627], [_G1609, _G1612, _G1615]].
On the other hand, if you first instantiate the variables A, B and C, you will get a different result:
?- A=1, B=2, C=3, findall(X, permutation([A,B,C],X), Z).
A = 1,
B = 2,
C = 3,
Z = [[1, 2, 3], [1, 3, 2], [2, 1, 3], [2, 3, 1], [3, 1, 2], [3, 2, 1]]
This didn't happend before in your query findall(X, permutation([A,B,C],X), Z), A = 1. because Prolog will first try to solve the condition findall(X, permutation([A,B,C],X), Z) and then A = 1

Prolog combining predicates

Just a small question about Prolog. Say I have used the built in predicate findall/3 to obtain a list and used the variable X as my output.
I'm wondering how I could then use this list in another predicate such as last/2 to find the last element of this list. If you could include a small example too that would help greatly.
First of all, since Prolog aims to be a logic programming programming language, there is nu such thing as output variables.
Nevertheless, say you know a variable X is bounded after a certain predicate and you intend to use this value when calling a new predicate, you can use Prolog's logical "and" ,/2. I'm putting "and" between quotes because this and differs sometimes from the natural understanding of how "and" in natural language behaves.
You can thus use a predicate:
findall(A,foo(A),X),last(X,L).
To first find all occurences of foo/1, extract the variable A, put these into a list X and finally get the last/2 element of X.
You can then for instance use this in a defined predicate:
last_foo(L) :-
findall(A,foo(A),X),
last(X,L).
If you run this for instance with:
foo(a).
foo(9).
foo(b).
The results are:
?- foo(A).
A = a ;
A = 9 ;
A = b.
and:
?- findall(A,foo(A),X).
X = [a, 9, b].
Now the result to obtain the last is:
?- findall(A,foo(A),X),last(X,L).
X = [a, 9, b],
L = b.
or:
?- last_foo(L).
L = b.

Nested list duplicate

I'm confusing myself and it'll be helpful if someone can point me in the right direction. I need to get duplicates out of a nested list. I thought I could simply find out how to get duplicates out of a regular list and then make a rule for getting subsets then somehow combine them and it'll work but I think I'm confusing myself more by doing that.
Here's what I have so far, it deletes the duplicates fine.
Removes Duplicates:
duplicate([],[]).
duplicate([H|T],C) :- var(H,T),!, duplicate(T,C).
duplicate([H|T],[H|C]) :- duplicate(T,C).
var(X,[H|_]) :- X==H,!.
var(X,[_|T]) :- var(X,T).
Subset Rule:
subset([],_).
subset([H|T],L):- member(H,L),subset(T,L).
currently if I call duplicate([1,2,2,3,4,a,a,a,b,b,b], X). it'll return X = [1,2,3,4a,b] which is correct but I want to be able to call duplicate([1,[2,[2,[1,[a,[a]]]]]], X). and have it return X = [1,2,a]
Is my thought process correct or am I thinking of this incorrectly?
You can just flatten the list as a preprocessing step:
?- flatten([1,[2,[2,[1,[a,[a]]]]]], L).
L = [1, 2, 2, 1, a, a].
And then use your existing duplicate on the flatten list: flatten([1,[2,[2,[1,[a,[a]]]]]], L), duplicate(L, X).

filter a range using a hash kind of list

I am c++ guy and i am completely new to prolog.
I am using sicstus prolog.
i came across a need as below:
lets say i have a variable
A={0,1,2,3}
B={-2,-1,0,1,2,3,4,5}
and i have hash kind of thing like
0-{3}
1-{4}
now i need to filter the values of A and B using this hash so that after the operation:
A={0,1}
B={3,4}
logic is values from A will be matched with keys of the hash
if the key exists then check for the value.if the value exists in B then the value in A remains.
otherwise value should be deleted.
in the same way it should be done for B with the values in the hash shoul dbe searched in A and if not present then it should be deleted in B.
means the exactly opposite way for B.
Could anybody please help?
I'd suggest you use lists to hold the keys and values of A and B, and a list of Key-Value pairs to hold your hashmap. That way you can use builtin helper predicates include/3 and memberchk/2 to suit your needs.
Then you can write a procedure that filters the items of A and B:
filter(A, B, Hash, FA, FB):-
include(filterkey(B, Hash), A, FA),
include(filtervalue(A, Hash), B, FB).
filterkey(B, Hash, Item):-
memberchk(Item-Value, Hash),
memberchk(Value, B).
filtervalue(A, Hash, Value):-
memberchk(Item-Value, Hash),
memberchk(Item, A).
Say if you have
A=[0,1,2,3]
B=[-2,-1,0,1,2,3,4,5]
Hash=[0-3, 1-4]
then:
?- A=[0,1,2,3], B=[-2,-1,0,1,2,3,4,5], Hash=[0-3, 1-4], filter(A, B,Hash, FA, FB).
Hash = [0-3, 1-4],
FA = [0, 1],
FB = [3, 4].
I'm sorry I don't have Sicstus available to test, and then I could be completely out-of-track, but you are handling a very peculiar kind of variables. Consider
?- write_canonical({1,2,3,4}).
{}(','(1,','(2,','(3,4))))
?- {1,2,3,4}={A}.
A = (1, 2, 3, 4).
Braces are really just a peculiar name for a tuple, and AFAIK are used just as syntactic device to introduce readable data in a DSL (Domain Specific Language), like for instance constraints in library(clpqr).
What I mean is that or
you are using the wrong representation for the task (gusbro addressed this problem, +1)
you are searching for a clp constraint extension (filtering?) not available in Sicstus. But then the question should be reformulated in better terms.
Anyway you could adapt gusbro' answer without changing your program if you add, for instance,
member_set(E, {','(E,_)}).
member_set(E, {','(_,T)}) :- member_set(E, {T}).
member_set(E, {E}).
to replace memberchk. include/3 must be rewritten also, but it's not so easy.
Otherwise, a conversion predicate
set_list({','(A,B)}, [A|R]) :- set_list({B}, R), !.
set_list({E}, [E]).
set_list({}, []).
could be handy:
?- set_list(S,[1,2,3]).
S = {1, 2, 3}.
?- set_list({1,2,3},L).
L = [1, 2, 3].

Prolog function iscontained?

I'm trying to make a Prolog predicate iscontained/2: iscontained(List, Search) where it returns true. if the Search is listed within the given List, false. if not. And if it is a variable that is inputted, then it just returns that it equals each element in the list.
Example:
?- iscontained([a, b, c], a).
true.
?- iscontained([a, b, c], d).
false.
?- iscontained([a, b, c], A).
A = a;
A = b;
A = c;
false.
I need a shove in the right direction, not asking for a hand out, unless you know a quick way to do it. Any help is appreciated, thanks.
Please note that the frequently proposed member/2 predicate admits solutions that are no lists at all:
?- member(e,[e|nonlist]).
true.
This is not a big problem in many situations, but should be mentioned nevertheless.
A natural, symmetric definition that only admits lists uses DCGs:
... --> [] | [_], ... .
iscontained(Es, E) :-
phrase((...,[E],...), Es).
The ... is a non-terminal which denotes an arbitrary sequence.
While this is entirely overkill for this tiny example, it gives you a template for more interesting patterns. Like
iscontainedtwice(Es, E) :-
phrase((...,[E],...,[E],...), Es).
You will need to consider two cases. I'll leave the body of the rules up to you.
iscontained([A|Xs],A)
iscontained([X|Xs],A)
[edited to remove reference to the empty list: the empty list contains nothing: if encountered, the predicate fails.]
Now that you certainly already came up with a solution, I'd like to mention one thing:
The classical version:
member(Item, [Item|_List]).
member(Item, [_Head|List]) :- member(Item, List).
leaves a choice point after having found the last element possible, ie:
?- member(A, [1, 2, 3]).
A = 1;
A = 2;
A = 3;
false.
while
member2(Item, [Head|List]) :-
member2(List, Item, Head).
member2(_List, Item, Item).
member2([Head|List], Item, _PreviousHead) :-
member2(List, Item, Head).
treats the empty list at the same time as the last element and allows optimization:
?- member2(A, [1, 2, 3]).
A = 1;
A = 2;
A = 3.
That's the version used in SWI-Prolog (and certainly Jekejeke Prolog and maybe others). Its author is Gertjan van Noord.
That's just meant as a reminder that, while the exercise of coming up yourself with a member/2 implementation is excellent, it should not lead you not use the built-ins afterwards, they're often fine tuned and more efficient!

Resources