Prolog Member Implemention - list

I'm trying to implement my own version of member for something I'm working on. As of now it looks like this:
search(X,[X | T]).
search(X, [H | T]) :-
search(X,T).
And it seems to work, however I have a few issues. I get a singleton warning on T and H. Also, I'm just not 100% sure on what the code actually does. From what I understand
search(X,[X | T]).
the first argument is my target, and the second argument is a list split into X and then everything else from list.
Then for
search(X, [H | T]) :-
search(X,T).
I'm not really sure what is happening, besides it calling itself recursively. How does it actually know it's in the list? Any clarification would be appreciated.
EDIT: I think I get it now.
I'm saying the first line is true when the list just contains my target as a fact. Then, I recursively go through the list until the only thing that remains is my target, in which case it's true. If the list ends up empty that it would be false. Is this correct?

The key to understanding Prolog is to grok the declarative reading of the code. So forget how it's going to work for now and just think about what is logically being said.
search(X, [X|T]).
This says
search(X, [X|T]) is true if the first argument and the first item of the second argument are the same
The "if" portion there is just how the pattern matching works. You get a singleton variable warning because you never used T. Prolog would rather you wrote search(X, [X|_]).
The second line says
search(X, [H|T]) is also true if search(X, T) is true.
Your other singleton variable warning is here because you made a variable H and then didn't do anything with it, so Prolog would prefer to see search(X, [_|T]) :- search(X, T)..
Hope this helps!

The accepted answer is great, I just want to clarify some things you added in your edit:
I'm saying the first line is true when the list just contains my target as a fact. Then, I recursively go through the list until the only thing that remains is my target, in which case it's true. If the list ends up empty that it would be false. Is this correct?
The parts "... is true when the list just contains my target" and "until the only thing that remains is my target" (emphasis mine) are incorrect and suggest a small misunderstanding.
Rather, search(a, [a, b, c]) is true because the target is the first element of the list in the second argument. Here a is not "the only thing that remains" in the list. It is just something that appears in the list in addition to other things that we don't need to care about.
You are correct about the last part: Yes, the search fails when it reaches the end of the list.

Related

Prolog - How can I return a list where each element appears only once?

I have a predicate set/2 that is supposed to instantiate the second argument to a list whose elements are only one occurance of each term from the first argument. What I have so far is:
set([],OutList).
set([X|InList],OutList) :- \+member(X,InList), append([X], OutList, OutListNew), set(InList,OutListNew).
set([X|InList],OutList) :- member(X,InList), set(InList,OutList).
And calling set/2:
set([1,1,2,3],X).
returns true. That's halfway there - I want X to be instantiated to [1,2,3] - but I'm not sure how to make X true in this case. Any help and explanations would be appreciated.
Your Prolog should warn you have a singleton in the first clause, that is
set([],OutList).
It means that when the execution hits such clause, it succeeds, but OutList remains unbound.
Now should be clear that you need to substitute OutList with the empty list.
Another bug is located in the second clause.
append([X], OutList, OutListNew) should be instead append([X], OutListNew, OutList). As a style note, it can be substituted by this unification: [X|OutListNew]=OutList, and then moved into the head.
sort/2 removes duplicates (msort/2 leaves duplicates, if that's what you want.
Also: https://www.swi-prolog.org/pldoc/man?predicate=list_to_set/2

Define a rule to determine if a list contains a given member

I have recently started learning prolog, and facing a problem with this question:
Define a rule to determine if a list contains a given member.
I searched all over stack overflow to get some links to understand this problem better and write solutions for it but couldn't find anything. Could anyone of you advice to solve this particular problem?
My Approach:
Iterative over the list and see if your member matches with head:
on(Item,[Item|Rest]). /* is my target item on the list */
on(Item,[DisregardHead|Tail]):-
on(Item,Tail).
Do you think my approach is correct?
What you have is indeed a "correct" implementation. The standard name for a predicate that does that is member/2, and is available (under that name) in any Prolog, and should be quite easy to find once you know its name.
Some things to note however. First, with the classical definition (this is exactly as in "The Art of Prolog" by Sterling and Shapiro, p. 58, and identical to yours):
member_classic(X, [X|Xs]).
member_classic(X, [Y|Ys]) :-
member_classic(X, Ys).
If you try to compile this, you will get singleton errors. This is because you have named variables that appear only once in their scope: the Xs in the first clause and the Y in the second. This aside, here is what the program does:
?- member_classic(c, [a,b,c,x]).
true ;
false.
?- member_classic(c, [c]).
true ;
false.
?- member_classic(X, [a,b,c]).
X = a ;
X = b ;
X = c ;
false.
In other words, with this definition, Prolog will leave behind a choice point even when it is quite obvious that there could not be further solutions (because it is at the end of the list). One way to avoid this is to use a technique called "lagging", as demonstrated by the SWI-Prolog library implementation of member/2.
And another thing: with your current problem statement, it might be that this is considered undesirable behaviour:
?- member_classic(a, [a,a,a]).
true ;
true ;
true ;
false.
There is another predicate usually called member_check/2 or memberchk/2 which does exactly what you have written, namely, succeeds or fails exactly once:
?- memberchk(a, [a,a,a]).
true.
?- memberchk(a, [x,y,z]).
false.
It has, however, the following behaviour when the first argument is a variable that might be undesirable:
?- memberchk(X, [a,b,c]).
X = a. % no more solutions!
There are valid uses for both member/2 and memberchk/2 IMHO (but interestingly enough, some people might argue otherwise).
Yes, your solution is correct and works in all directions. Nice!
Notes:
Your solution is in fact more general than what the task asks for. This is a good thing! The task, in my view, is badly worded. First of all, the first clause is not a rule, but a fact. It would have been better to formulate the task like: "Write a Prolog program that is true if a term occurs in a list." This leaves open other use cases that a good solution will also automatically solve, such as generating solutions.
This common predicate is widely known as member/2. Just like your solution, it also works in all directions. Try for example ?- member(E, Ls).
The name for the predicate could be better. A good naming convention for Prolog makes clear what each argument means. Consider for example: element_list/2, and start from there.

searching in list getting true infinitely in prolog

I tried to code a Prolog program that takes 2 value and calculates if the pair is valid or not. If pairs are in different lists, then pairs will be valid and they can make match. If two team in same list(group) then they can't make match which means false.
when i started the program it doesn't show anything. I thought there would be infinite searching or looping. Then tried that simple code
GroupB=[china,usa,chile,italy].
member(X,[X|_]).
member(X,[_|T]):-
member(X,T).
match(X):-
member(X,GroupB).
In that code i saw that program always gives me true. I typed; to SWI-Prolog it gave me another true, i typed ; again another true then i realized that the problem should be in that searching part. Thanks for all interests from now. All suggestions are welcome.
edit:
I edited the code like that to try a different style
GroupA([germany,brazil,turkey,korea]).
GroupB([china,usa,chile,italy]).
member(X,[X|_]).
member(X,[_|T]):-
member(X,T).
memberence(X):-
GroupA(L).
GroupB(M).
member(X,L).
member(X,M).
collision(X,Y):-
GroupA(L),
member(X,L),
member(Y,L).
GroupB(L),
member(X,L),
member(Y,L).
match(X,Y) :-
GroupA(L),
memberence(X),
memberence(Y),
\+collision(X,Y).
now i got:
ERROR: Undefined procedure: match/2
ERROR: However, there are definitions for:
ERROR: catch/3
although there is a match(X,Y) procedure why it gives me undefined match/2 error.
GroupA=[germany,brazil,turkey,korea].
GroupB=[china,usa,chile,italy].
member(X,[X|_]).
member(X,[_|T]):-
member(X,T).
memberence(X):-
member(X,GroupA).
member(X,GroupB).
collision(X,Y):-
member(X,GroupA),
member(Y,GroupA).
member(X,GroupB),
member(Y,GroupB).
match(X,Y) :-
memberence(X),
memberence(Y),
\+collision(X,Y).
a)
You have a dot that must be comma in:
collision(X,Y):-
member(X,GroupA),member(Y,GroupA).
member(X,GroupB),member(Y,GroupB).
b)
Better you do not redefine "member", it is standard.
c)
If I change dot by comma in:
collision(X,Y):-
GroupA(L),member(X,L),member(Y,L),
GroupB(L),member(X,L),member(Y,L).
this statement will fail always because there are no list "L" common to GroupA and GroupB.
d)
If we take what seems the original request "takes 2 value and calculates if the pair is valid or not. If pairs are in different lists, then pairs will be valid and they can make match. If two team in same list(group) then they can't make match which means false."
the solution seems obvious:
match(X,Y) :- groupA(A), member(X,A), groupB(B), member(Y,B).
match(Y,X) :- groupA(A), member(X,A), groupB(B), member(Y,B).
You have 2 big problems.
First, you seem to use . and , interchangeably.
Second, you fail to understand Prolog's scoping rules. Anything that isn't asserted into the prolog database is scoped to the immediate statement or the clause of the predicate of which is a part. If you want somebody to know about it, it either has to be a part of the prolog database or passed as an argument. Thus, when you say something like
GroupB = [china,usa,chile,italy].
The variable GroupB Is unified with the list [china,usa,chile,italy]. At which point, the assertion succeeds, and both the newly-bound variable and the list with which it was unified ** go out of scope** and cease to exist. Then, when you attempt to reference it later on:
GroupB=[china,usa,chile,italy].
.
.
.
match(X) :- member(X,GroupB).
The variable GroupB is unbound. Your implementation of member/2,
GroupB=[china,usa,chile,
member(X,[X|_]) .
member(X,[_|T]) :- member(X,T) .
is more than willing to act in a generative manner when given an unbound variable as its 2nd argument, generating lists of variable, successively (and infinitely) longer on backtracking.

Declarative interpretation of this program that says if an element belongs to a list

From what I have understood the declarative paradigm indicate what is important to reach the solution and not how reach it but, being accustomed to think procedurally, I often make confusion...
So the solution is this one:
mymember(X, [X|_]).
mymember(X,[_|T]) :- mymember(X,T).
This is my declarative interpretation of this simple program:
1) X belong to the list if it is TRUE that X is the Head of this list (if the head element of the list unifies with the X element that I would know if is in the list)
2) If the first fact is not true (X don't unifies with the first list element) the program try to execute the second rule (and maybe here I have some interpretation problem). This rule say that: the head is true if the body of the rule is true)
The head of rule say that: X belongs to the TAIL of the list (I use an anonymous variable using the _ character to say that don't care of the first element of the list)
So this rule say that: It is TRUE that the X element belong to list without its head if it is TRUE that the X element belong to the tail of the list
Is it a correct declarative and logic interpretation of this program or I am missing something?
You're reading them as exclusive-or, but they're actually inclusive-or. Both 1) and 2) are correct, minus the connective "if the first fact is not true". It's not necessary for 1) to be false for 2) to hold. In other words, it can be true that X is both the head of the list and present in the tail of the list (for instance mymember(a, [a, b, a]).
Edit: responding to your comment.
There's a language barrier issue here, so let me try answering your question with yes and no.
Yes, that using ; produces another answer is evidence that Prolog was able to compute alternative answers. In one sense, ; triggers backtracking manually, but in another sense it is Prolog asking you if this is the answer you wanted, and then you're able to say "yes" or "no." When you say ; you're telling Prolog, in essence, "this isn't the right answer." But this is not the only way to trigger backtracking; in fact, most of the time you won't trigger it manually at all.
For instance, let's look at this:
even_member(X, L) :- member(X, L), 0 is X mod 2.
?- even_member(X, [1,5,17,23,4,19]).
X = 4 ;
false.
So here I defined a predicate that says, declaratively, X is an even_member of L if X is a member of L and X mod 2 = 0. When I used the predicate, we got the answer X = 4. We then pressed ; to say, this isn't the right answer, and Prolog said there are no more answers. But internally, member(X, L) backtracked 5 times before it found an element that satisfied the second part of the predicate--in other words, the statement 0 is X mod 2 tells Prolog that 1, 5, 17 and 23 are "wrong" the same way we do by pressing ; interactively. When we said we wanted another answer, we engaged the same machinery, so Prolog went back to member(X, L), found 19, and then found that 19 is not divisible by two and gave up.
Prolog backtracked six times, five of those times just to get the one answer. We only asked it to backtrack once, and it happened that it was the last possibility so it didn't backtrack again.
Let me try:
mymember(X, [X|_]).
X is a member of the list if it's the first element of the list
mymember(X,[_|T]) :- mymember(X,T).
X is a member of the list if it's a member of the rest of the list.
Suppose I give you a stack of (paper) programmer resumes and say "see if there is a programmer who knows Prolog among these"
What do you do? You look at the top resume. If that programmer knows Prolog, you're done.
If not, then the only way there can be such a resume is if it's in the rest of the stack.
point 2) doesn't hold: Prolog will try each rule searching for a solution.
But it will follow a strictly specified order searching in your database, resulting in a depth first search of the solution space.
I would read
X is a member of a list if it is the first element (i.e. unify the head, clause 1), or is a member of the tail (clause 2).

Understanding the splitting in Swi-prolog

I have this code for splitting input list into its halves. It seems to be OK.
halve(List,A,B) :- halve(List,List,A,B), !.
halve(B,[],[],B).
halve(B,[_],[],B).
halve([H|T],[_,_|T2],[H|A],B) :-halve(T,T2,A,B).
Ok, so I tried to decode it. The beginning is clear:
"Halve took list and 2 logic variables" is this:
halve(List,A,B)
(1) Then continuous this part:
:- halve(List,List,A,B).
And this means, that I am creating new two lists (List, List) from the first one or what? What exacly represents ":-"? I guess the new lists = halves will be the A, and B, right?
(2) Second, please, I don't quite get these two lines:
halve(B,[],[],B).
halve(B,[_],[],B).
Maybe you could explain it on some examples, please?
(3) Well, I hope after your explanation of (1) and (2), I'll get the final part by myself...
halve([H|T],[_,_|T2],[H|A],B) :- halve(T,T2,A,B).
Thank you very, very much for helping me.
Ok, our first problem already has its solution. Long story short, it works like this:
halve([1,2,3,4,5],[1,2],[3,4,5]).
->true
If you notice it splits the list into its halves but if the list has an odd number of the elements, the second half is the bigger one.
Now what I want to obtain is to have the first one bigger.
So I'm thinking about this:
I'm going to reach this:
Halves_div([1,2,3],A,B).
A=[1,2],
B=[3].
Let's say my input is list: [1,2,3]. So I'll start with splitting list's head and tail: [H|T] and then I will merge the H with new empty list - my 1st Half (A).
After that I have A=[1], B=[] and Input=[2,3].
For merging I have:
merge([],List,List).
merge([H|T],List,[H|New]) :- merge(T,List,New).
And one more thing - I need to check whether the 1st half is already >= 2nd half, right?
So this is my idea and only thing I'd love you to help me is to write it in prolog. I'm kinda confused how to put it together.
Thanks!
It seems my idea of solution is too complicated and I found something better!
To start, a Prolog clause looks like that:
Head :- Body
You can read that as "Head if Body", or "Body implies Head".
Note that sometimes you just have
Head
That's because Head is always true. Instead of calling Head a clause, we rather call it a fact in this case.
So here, we have:
halve(List,A,B) :- halve(List,List,A,B).
That means that halve(List, A, B) is true if halve(List, List, A, B) is true. Concretely it's just a way to delegate the work of halve/3 to halve/4, a so called worker predicate.
Why do we need a worker predicate? Well, because here we'd like to use another variable to calculate our A and B terms. But we couldn't do that with halve/3 because the 3 argument spots of halve/3 were already taken by the input list, List, the first half of the result, A and the second half of the result, B.
About the List, List thing, it's just a way to say that we call halve/4 with the same first and second argument, like you would in any programming language.
Then the interesting stuff starts. Prolog will try to prove that halve/4 is true for some given arguments. Let's say to illustrate the execution that we called halve/3 this way:
?- halve([1, 2], A, B).
Then, if you followed what I talked about previously, Prolog will now try to prove that halve/3 is true by proving that halve/4 is true with the following arguments: halve([1, 2], [1, 2], A, B)..
To do that, Prolog has 3 choices. The first choice is the following clause:
halve(B,[],[],B).
Obviously, that won't work. Because when Prolog will try to fit the second argument of the caller "in" the second argument of the callee through unification, it will fail. Because
[1, 2] can't be unified with [].
Only two choices left, the next is:
halve(B,[_],[],B).
Same thing here, Prolog cannot unify [1, 2] and [_] because _ is just a variable (see my post about the anonymous variable _ if you've troubles with it).
So the only chance Prolog has to find a solution to the problem you presented it is the last clause, that is:
halve([H|T],[_,_|T2],[H|A],B) :- halve(T,T2,A,B).
Here, Prolog will find a way to unify thing, let's see which way:
we have to unify [1, 2] with [H|T]. That means that H = 1. and T = [2].
we have to unify [1, 2] with [_,_|T2]. that means that T2 = [].
now we start to build our results with the next unification, ie A = [H|A'] (I primed the second A because variables are scoped locally and they are not the same). Here we tell that when we'll have our result calculated from the body of the clause, we'll add H to it. Here H is 1 so we already know that the first element of A will be 1.
Ok ok, unification succeeded, great! We can proceed to the body of the clause. It just calls halve/4 in a recursive manner with those values (calculated above):
halve([2], [], A, B).
And here we start all over again. Though this time things will be fast since the first choice Prolog has will be a good fit:
halve(B,[],[],B).
can be unified to
halve([2], [], A, B).
with those values: A = [] and B = [2].
So that's a good step, we now reached the "base case" of the recursion. We just have to build our result from bottom to top now. Remember when we called recursively our predicate halve/4 a few steps above? We had already said that the first element of A would be 1. Now we know that the tail is [] so we can state that A = [1]. We hadn't stated anything particular about B so B = [2] is left untouched as the result.
Now that I detailed the execution, you might wonder, why does this work? Well, if you pay attention, you'll note that the second argument of halve/4 is gone through twice as fast as the first one. [H|T] vs [_, _|T2]. That means that when we hit the end of the list with our second argument, the first one is still at the middle of our list. This way we can divide the thing in two parts.
I hope I helped you catch some of the subtle things at work here.
halve(List,A,B) copies first half of List to A and unifies second half with B
That will be true when length of our list will be even: halve(B,[],[],B).
That will be true when length of out list will be odd: halve(B,[_],[],B).
halve([H|T],[_,_|T2],[H|A],B) :- halve(T,T2,A,B).
Here we are setting 2 lets call them 'pointers' in each step we copy one element from beginning of our list to A because we want get first half.
Because in each step we are removing 2 elements from our list [_,_|T2] Predicate will stop when list will have only one left element or empty, then it will unify rest of our list with B. If you cant understand use trace/0
This version might prove useful ...
split_in_half(Xs, Ys, Zs) :- length(Xs, Len),
Half is Len // 2, % // denotes integer division, rounding down
split_at(Xs, Half, Ys, Zs).
split_at(Xs, N, Ys, Zs) :- length(Ys, N), append(Ys, Zs, Xs).