find sister relation from family tree using prolog - prolog

I have facts: male, female and child.
eg.
/* tg and yem are mother and father. rika,kiku and susu are children*/
female(rika).
female(tg).
male(kiku).
male(susu).
male(yem).
child(rika,tg).
child(kiku,tg).
child(susu,tg).
child(rika,yem).
child(kiku,yem).
child(susu,yem).
Now I need a query to extract sister relation like
sister(Sister1,Sister2):-
female(Sister1),
child(Sister1,X),child(Sister2,X),
Sister1 \= Sister2.
But it results duplicate responses. How can I improved to get single answers?

Since your predicate always terminates, you can use the predicate setof/3 to remove duplicate solutions:
?- setof(X-Y, sister(X,Y), Xs).
Xs = [rika-kiku, rika-susu].
The first argument defines a term template representing one solution, the second defines the goal of which you want to collect the answer substitutions and the third argument is the list of instantiated template terms.
You will still have redundancy if a parent has two daughters, which become sisters. E.g. if you add the facts
female(ala).
child(ala,tg).
child(ala,yem).
to your knowledgebase, then the query contains all sisters twice.
?- setof(X-Y, sister(X,Y), Xs).
Xs = [ala-kiku, ala-rika, ala-susu, rika-ala, rika-kiku, rika-susu].
One reason is that you defined your predicate sister with two arguments : sister is a relation between Sister1 and her sibling. (The way you wrote it, the variable name Sister2 gives the wrong intuition that the sibling is also female, but that's just a side note). If we only want to know who is a sister, this is a set (or one-place predicate) - let's call it is_sister/1:
is_sister(Xs) :-
setof(X, Y^sister(X,Y), Xs).
If you look at the answer substitutions, the queries setof(X, sister(X,Y), Xs). and setof(X, Y^sister(X,Y), Xs). differ a lot. The reason is that Y is free in the first template and you will receive a set depending on the possible substitutions of Y. In the second example, the Y^ binds the variable - we obtain all instantiations of X in one set, independent of the binding of Y.

Related

Prolog and List Unification

I'm trying to further my understanding of Prolog, and how it handles unification. In this case, how it handles unification with lists.
This is my knowledgebase;
member(X, [X|_]).
member(X, [_|T]):- member(X, T).
If I'm understanding the process correctly. If member(X, [X|_]) is not true, then it moves into the recursive rule, and if X is in list T, then [_|T] is unified with T.
So what happens to the anonymous variable in my recursive predicate? Does it get discarded? I'm having difficulty understanding the exact unification process with lists, as [_|T] is two variables, rather than one. I'm just trying to figure out how the unification process works precisely with lists.
Assume that _ is Y
member(X, [Y|T]):- member(X, T).
Then this is True regardless Y. Now you are "returning" member(X, T). In other words, you are discarding Y and "returning" member(X, T).
_ means, whatever it is, ignore that variable.
The _ is just like any other variable, except that each one you see is
treated as a different variable and Prolog won't show you what it
unifies with. There's no special behavior there; if it confuses you
about the behavior, just invent a completely new variable and put it
in there to see what it does.
In your case, your function check if a given element exists on a list, so, you take first element of the list, check if is equal, if not, you discard that element and moves on.
I think your primary question of how lists are represented as variables has been adequately answered, but I sense there are some other aspects to Prolog that need clarification.
To understand Prolog predicates and clauses, it's a good idea not to think of them as "functions" that "return" things, even metaphorically. It can lead you down the dark path of imperative thinking in Prolog. :)
In considering the predicate:
(1) member(X, [X|_]).
(2) member(X, [_|T]) :- member(X, T).
Think of member/2 as a relation which describes when element X is a member of the list L, and the clauses are the rules for determining when it is true.
I'll assume that you already know about how lists are represented in Prolog based upon other answers (e.g., Will Ness' detailed answer).
The first clause says:
(1) X is a member of [X|_] regardless of what the tail of the list [X|_] is
In that notation, the variable _ represents the tail of list [X|_] and X represents the first element of that list. It's trivially true that X is a member of this list, so member(X, [X|_]). is a fact. It's true regardless of what the tail of the list is, so we just use _ (an anonymous variable) since this rule doesn't need the information. Prolog doesn't technically "throw the value away" but the programmer throws it away because the programmer isn't using it. If we had, instead, said, member(X, [X|T]). that would work fine, but we're not using T. Prolog might instantiate it, but it wouldn't be used. It's like assigning x = 3 in C but not using it's value. In this case, Prolog will indicate a warning about a "singleton" variable. Watch for those, because it often means you misspelled something or forgot something. :)
The next rule is recursive. It says:
(2) X is a member of list [_|T] if X is a member of the tail (T) of that list, regardless of what the first element of the list is
Here we're considering the less trivial case where the first element in the list may not be a match to X, so the truth value of member(X, L) depends, in this rule, upon the truth value of member(X, T) where T is the tail (everything but the first element) of L. The rule does not unify member(X, [_|T]) with member(X, T), so it does not unify T with [_|T] as you might suppose. The :- operator defines a rule or implication (note the if in the rule description). [N.B., If you were to unify these terms, it would be done with with the unification operator, =/2: member(X, [_|T]) = member(X, T)].
On the recursive query member(X, T), Prolog goes back to the top, the first rule, and attempts to unify the first argument X with the head of the second argument (which is the original list minus its first element, or head) and, if it doesn't match, goes to rule #2 again, continually checking the tail as well, until it can unify. If it gets to the point where the tail is empty ([]) and hasn't been able to unify X with any elements, the predicate fails because there are no facts or rules that match member(X, []). However, if it does unify X with an element, it succeeds (it does not "return a value* in the sense that a function would in other languages) and reveals the values of any variables it instantiated in the arguments in the process, or simply will succeed if all the arguments passed are already instantiated. If there are more rules to check after succeeding (there was what's called a choice point), it will (if you tell it to) go back and check for more solutions and, if it finds them, display them as well. Or display no or false if there are no more.
Looking at an example query, is b a member of [a,b,c]?
member(b, [a,b,c]).
Prolog will first try to unify the query with a fact or the head of a predicate. The first one it finds is:
member(X, [X|_]).
In attempting to unify, X = b, but [a,b,c] (or, [a|[b,c]] in the head-tail notation) doesn't unify with [b|_](note the head elementsaandb` mismatch). Prolog then moves on to the next clause:
member(X, [_|T]) :- member(X, T).
In unifying member(b, [a,b,c]) with the head, it comes up with:
member(b, [_|[b,c]]) :- member(b, [b,c]).
It now has the recursive query to chase down: member(b, [b,c]). Since it's a new query, it starts at the top again and attempts to unify this with member(X, [X|_]). Now, it's successful, because member(b, [b,c]) (or, member(b, [b|[c]])) matches this pattern: member(b, [b|_]).
Therefore, the member(b, [a,b,c]). succeeds and Prolog will return "true". However, it's not done yet because it left what's called a choice point. Even though it matched member(b, [b,c]) with the first clause, it will still want to go back and find more cases that make it succeed, and there's still another clause to pursue. So, Prolog will go back and try member(b, [b,c]) against the second clause, matching member(b, [b|[c]]) to member(b, [_|[c]]) and doing another recursive query, member(b, [c]) and so on until it ultimately fails to find another solution. This is why the query looks something like this:
| ?- member(b, [a,b,c]).
true ? ;
no
| ?-
It first succeeds, but then we ask for more (with ;) and it then fails (no). This confuses some Prolog beginners, but it's because we've asked Prolog to get another solution, and it said there are none.
Because Prolog continues to try to find solutions (upon request), you can also use a variable in the query:
member(E, [a,b,c]).
This query runs the same way as the prior example, but now I have a variable as the first argument. Prolog will successfully match this to the first clause: member(E, [a,b,c]) unifies with member(X, [X|_]) via E = a. So you'll see something like:
| ?- member(E, [a,b,c]).
E = a ?
If we now ask for more solutions with ;, Prolog goes back and attempts the second clause, unifying member(E, [a|[b,c]]) with member(X, [_|T]) yielding _ = a (which is ignored in the predicate) and T = [b,c]. It then recursively queries, member(E, [b,c]) and, since it's a new query, goes back to the top and matches member(X, [X|_]) again, this time with E = b. So we see:
| ?- member(E, [a,b,c]).
E = a ? ;
E = b ?
And so on. member(E, [a,b,c]) will find all the values of E which make member(E, [a,b,c]) true and then finally fail after exhausting all the elements of [a,b,c]).
[A|B] represents a list where A is the Head element and B is the whole rest list.
So to explain you the algorithm shortly:
Clause: If X is the first element of the list the predicate succeeds.
Clause: If that's not the case, we try to find X in the tail of the list. Therefore, we call member recursively but instead of passing the whole list we now pass the list EXCEPT the head element. In other words, we walk through the list step by step always looking at the head element first. If that is not our element, we dig further.
Think of the anonymous variable _ just as a variable you do not need later. The algorithm would also work, if you replaced _ by a capital letter, however it would give you a warning that you named a variable that you never use.
A list is just a compound term with the '.' functor:
1 ?- [_|T] = .(_,T).
true.
2 ?- [_|T] =.. X.
X = ['.', _G2393, T].
The usual process of structural unification of compound terms apply:
3 ?- [A|T] = .(B,R).
A = B,
T = R.
[A|T] is really .(A,T) so the functors (.) and the arities (both terms are binary, of arity 2) match, so the respective constituents are matched as well.
Yes, the anonymous variable _ is ignored for the purposes of reporting the unification results. Otherwise it is just a fresh uniquely named variable.
it moves into the recursive rule, and if X is in list T, then [_|T] is unified with T.
Not quite. The unification happens before the "moving on", as part of the clause selection. To unify a list L with [_|T] is to select its "tail" and have T referring to it. E.g.
4 ?- L = [1,2,3], L = [_|T].
L = [1, 2, 3],
T = [2, 3].
(_ is 1 but is not reported).

What exactly is member(b,X)?

Today I came across this query:
?- member(b,X).
The program was:
member(X,[X|_]).
member(X,[_|T]) :-
member(X,T),
!.
When I ran the query, I got these answers:
?- member(b,X).
X = [b|_G1560] ;
X = [_G1559, b|_G1563].
What exactly is that? What does this query do?
The query member(b,X) generates lists containing b. As the second argument is not instantiated, you have a (theoretically) infinite number of solutions. The first solution will have b in the first position, the second solution will have b in the second position and so on. Moreover, if you look closely to any of the solutions, you see that it represents any list with a b on that position. For example, the first solution is [b| _]. As the list tail is not instantiated (see the member/2 predicate base case), this solution unifies with any list with b in the head position.
If you want to make the member/2 deterministic, i.e. if you want to use the predicate only to check if a term is a member of a list, you will need to add a cut in the base clause, not in the recursive clause as #false noted:
member(Head, [Head| _]) :-
!.
member(Head, [_| Tail]) :-
member(Head, Tail).
The resulting predicate is usually named memberchk/2 and available as such as a library predicate.

How can i tell if an object is unique

i just can't get my head around this problem i'm having with prolog. Only just started, but i can't seem to find a way to find out if an object is unique. Heres my code:
/* (Student Name, Student Number)*/
Student(stuart, 11234).
Student(ross, 11235).
Student(rose, 11236).
Student(stuart, 11237).
how can i find out if a student is unique. Take for example Stuart, there's two students named Stuart, so Stuart is not unique. How could i write a procedure to tell if its another Student called Stuart.
I've tried spending so many hours on this, but i can't seem to get my head around dealing with the original Stuart rather than the other Stuart because i can't exclude the one i'm trying to find out if its unique.
Thanks for the help.
With your database example this could do
unique(S) :-
student(S, N), \+ (student(S, M), M \= N).
as it yields
?- unique(S).
S = ross ;
S = rose ;
false.
Generally, Prolog is targeted toward existence of solutions. Then predication about cardinality need some support from the 'impure' part of the language: nb_setarg it's currently our best friend when we need to efficiently tracking cardinality.
Using a metapredicate like this:
%% count_solutions(+Goal, ?C)
%
% adapted from call_nth/2 for http://stackoverflow.com/a/14280226/874024
%
count_solutions(Goal, C) :-
State = count(0, _), % note the extra argument which remains a variable
( Goal,
arg(1, State, C1),
C2 is C1 + 1,
nb_setarg(1, State, C2),
fail
; arg(1, State, C)
).
:- meta_predicate count_solutions(0, ?).
you could solve the problem without considering the second argument
unique(S) :-
student(S, _), count_solutions(student(S, _), 1).
The same predicate could use aggregate_all(count, student(S,_), 1) from library(aggregate), but such library currently builds a list internally, then you could consider the answer from Peter as easier to implement.
There are probably quite a few ways to solve this problem but I would do it this way:
% a student has a name and a number
student(stuart, 11234).
student(ross, 11235).
student(rose, 11236).
student(stuart, 11237).
This code says "find a list the same length as the number of students with Name" and then "make Count the same as the length of the list":
% for every student name there is an associated count of how many times
% that name appears
number_students(Name, Count) :-
findall(_, student(Name, _), Students),
length(Students, Count).
This predicate will only be true if the number_students is 1:
% a student name is unique (appears once and only once) is the
% number_students count is 1
unique_student(Name) :-
number_students(Name, 1).
Testing:
12 ?- unique_student(ross).
true.
13 ?- unique_student(rose).
true.
14 ?- unique_student(bob).
false.
15 ?- unique_student(stuart).
false.
This is an easy way to solve the problem, but it isn't a great Prolog solution because you cannot say things like "give me a unique student name" and get a list of all the unique names.
Some comments on the code you have. This is not a fact:
Student(Ross).
These are two different facts (in SWI-Prolog, at least):
student(ross).
student('Ross').
In other words, predicate names must start with small letters, and identifiers starting with a capital letters denote variables, not atoms. You can put any character string in single quotes to make it a valid atom.
Now this out of the way, it is not clear what you are aiming at. What are you going to do with your unique student? How do you know the first one is the one you are looking for, and not the second? And why not use the student number for that (at least in your example the two Stuarts seem to have different numbers)?

Compare results return from a query

When I run a query, it can return zero, one or more than one results. How can I "save" these results so that I can compare them later, or how can I compare them on the fly?
For example, I have these facts:
father(john, mark).
father(john, michael).
age(michael, 10).
age(mark, 12).
Now if I run a query like this
?- father(john, X).
it will return mark and michael, but how can I compare the age of mark and michael? In fact, how can I even know that the query will return more than one results?
The idea is that I want to get the eldest son of a father
What you're running into here is the fact that on backtracking, Prolog releases the variable bindings it found when it produced the previous result. This feature causes a lot of consternation in the early days, so know that you're not alone, we were all there once.
The first thing you should do is try to let go of the need to tell Prolog how to get the result, and instead focus on telling Prolog how to distinguish the result you want logically. This is logic programming, after all. :) When you say "how can I compare the age of mark and michael?" you're hiding the real question behind the assumption that once you know how to hold onto things you can find the answer yourself. But you don't want to find the answer yourself, you want Prolog to find it!
Let's take an example. Say you want to find out who is the youngest child of whom. You can do this logically:
?- father(Father, Child),
age(Child, YoungestAge),
\+ (father(Father, Child2),
age(Child2, Younger),
Younger < YoungestAge).
Father = john,
Child = michael,
YoungestAge = 10.
This would be inefficient with a large database, unfortunately, since Prolog will have to search every age/2 fact to find all the children of a particular parent. Presumably Prolog will index these predicates and that may be enough to save us depending on how you use it, but it doesn't look like a strategy you can apply universally. But you can't beat the logical reading of this query: supposing I have a father Father of child Child, and supposing that Child's age is YoungestAge, there is no Child2 of this same Father whose age is Younger than YoungestAge.
Frequently, you do need all the solutions, and for that there are three predicates: setof/3, bagof/3 and findall/3. They all have basically the same API with slightly different semantics. For instance, if you want all the children for a parent, you can use setof to get them:
?- setof(Child, father(john, Child), Children).
Children = [mark, michael].
You'll need a bigger fact database to see the effect of the differences between the two, but that's a different question. In short, setof/3 will get you a sorted list of unique answers whereas bagof/3 will get you an unsorted list with all the answers. findall/3 does the same thing, with a difference in the way it treats variables. In my experience, setof/3 and findall/3 tend to be used a lot more than bagof/3.
If the work you're doing necessitates it, or if efficiency demands it, you can use these meta-predicates to find all the possible solutions and walk through the list doing whatever processing you need to do.
As for the question "how can I even know that the query will return more than one result?" the answer is basically you can generate them all and see how many you had (findall(..., Answers), length(Answers, Count)) or you can use once/1 to ensure that you get a single solution. once is great for making non-deterministic predicates deterministic; the effect is basically the same as putting a cut right after the clause. For instance:
?- father(john, X).
X = mark ;
X = michael.
?- once(father(john, X)).
X = mark.
?- father(john, X), !.
X = mark.
In general it is recommended that you use once/1 over explicit cuts, if possible.
Let me know if this helps.
just a footnote on Daniel answer:
eldest(Father, Child) :-
findall(A/C, (father(Father, C), age(C, T), A is -T), L),
sort(L, [_/Child|_]).
I used the trick of negating the age to get the list in reverse order.
Here a 'one liner', does just the same as above:
eldest(Father, Child) :-
setof(A/C, T^(father(Father, C), age(C, T), A is -T), [_/Child|_]).
edit if your Prolog has library(aggregate), there is a cleaner way to get the result:
eldest(Father, Child) :-
aggregate(max(A, C), (father(Father, C), age(C, A)), max(_, Child)).

Simple Prolog delete from list

(This is NOT a coursework question. Just my own personal learning.)
I'm trying to do an exercise in Prolog to delete elements from a list. Here's my code :
deleteall([],X,[]).
deleteall([H|T],X,Result) :-
H==X,
deleteall(T,X,Result).
deleteall([H|T],X,[H|Result]) :- deleteall(T,X,Result).
When I test it, I first get a good answer (ie. with all the Xs removed.) But then the backtracking offers me all the other variants of the list with some or none of the instances of X removed.
Why should this be? Why do cases where H==X ever fall through to the last clause?
When you are using (==)/2 for comparison you would need the opposite in the third rule, i.e. (\==)/2. On the other hand, such a definition is no longer a pure relation. To see this, consider deleteall([X],Y,Zs), X = Y.
For a pure relation we need (=)/2 and dif/2. Many Prologs like SWI, YAP, B, SICStus offer dif/2.
deleteall([],X,[]).
deleteall([H|T],X,Result) :-
H=X,
deleteall(T,X,Result).
deleteall([H|T],X,[H|Result]) :-
dif(H,X),
deleteall(T,X,Result).
Look at the answers for deleteall([X,Y],Z,Xs)!
Edit (after four years):
More efficiently, but in the same pure vein, this can be written using if_/3 and (=)/3:
deleteall([], _X, []).
deleteall([E|Es], X, Ys0) :-
if_( E = X, Ys0 = Ys, Ys0 = [E|Ys] ),
deleteall(Es, X, Ys).
The last clause says that when removing X from a list, the head element may stay (independently of its value). Prolog may use this clause at any time it sees fit, independently of whether the condition in the preceding clause is true or not backtrack into this clause if another clause fails, or if you direct it to do so (e.g. by issuing ; in the top-level to get the next solution). If you add a condition that the head element may not equal X, it should work.
Edit: Removed the incorrect assertion I originally opened with.

Resources