Three Prolog questions include grandparent - prolog

This program will be tested using SWI Prolog.
Family.pl contains facts about family members, who is married to whom, sorts of things.
Rules must be added at the bottom and submit the modified file.
Write a motherInLaw(X,Y) predicate that means X is Y’s mother-in-law.
Write a grandParent(X,Y) predicate that means X is Y's Grandparent.
Write a grandMother(X,Y) predicate that means X is Y's Grandmother.
Thank you guys!
here are my own answers, could you please take a look and tell me if they are correct? Thanks
motherInLaw(X, Y) : mother(X, Z),couple(Z, Y)
grandParent(X, Y) : parent(X, Z),parent(Z, Y)
grandMother(Z, Y) : mother(X, Z),parent(Z, Y)

You need to write :- instead of : and . at the end of each clause
The grandmother/2 predicate looks very strange. Actually I think the head of the clause should be grandMother(X,Y).

Related

Prolog "recursive" query

I've started learning Prolog recently and came across a problem.
Some people sit around a table. We are given the fact sits_right_of(X, Y) (X sits right of Y). Then I wrote the next rules:
sits_left_of(X, Y) :- sits_right_of(Y, X) (X sits left of Y);
are_neighbors_of(X, Y, Z) :- sits_left_of(X, Z) (X sits left to Z and Y sits right to Z);
next_to_each_other(X, Y) :- are_neighbors_of(_, X, Y); are_neighbors_of(X, _, Y) (X sits next to Y).
How can I find out who is the person who sits two places right (or left) to a given person? Is there some kind of recursive query like sits_right_of(sits_right_of(X, alex))? Do I need to write another rule for finding out who sits n places away from somebody?
You obtain values from a procedure the same way you enter them. Introduce a new variable and try to satisfy sits_right_of(Y, alex). Then, this must also be satisfied: sits_right_of(X, Y). The procedure can be defined like this:
sits_two_places_right_of(X, Y) :- sits_right_of(X, Z), sits_right_of(Z, Y).
Yes, such a procedure can be created analogically to this for every number or persons, or using arithmetics, if you want to make it a parameter.

Prolog - converting succ representation into decimal

This is my code:
numeral(0).
numeral(succ(X)) :- numeral(X).
convertToD(A,0).
convertToD(succ(S), Y) :- numeral(S), Y1 is Y-1, convertToD(S, Y1).
Why does this give me such an output?
convertTo(succ(succ(0)), N).
N = 0 ;
ERROR: convertTo/2: Arguments are not sufficiently instantiated
Well, you're getting more than one answer because of this:
convertToD(A,0).
What you mean to have here is convertToD(0, 0), because otherwise you're saying "convertToD is true between anything and 0" when you mean "convertToD is 0 for 0." This is also why Prolog thinks you have multiple results.
Having given it some thought and noticed a question this question is a duplicate of, I see what you were trying to accomplish with the second clause. What you're trying to do is emulate the clpfd solution from there in ordinary Prolog. With clpfd:
convertToD(succ(S), Y) :- numeral(S), Y0 #= Y-1, convertToD(S, Y0).
A straightforward copy of that into vanilla Prolog gets us your code here, but what doesn't happen is all the magic clpfd brings to the table. Without clpfd, it's very difficult to make a predicate that works for any instantiation combination and never loops. One thing that helps is to move the arithmetic last:
convertToD(succ(S), Y) :- numeral(S), convertToD(S, Y1), succ(Y1, Y).
This gets us a predicate with all the desirable properties, except it loops here:
?- convertToD(X, 3).
X = s(s(s(0))) ;
^CAction (h for help) ? abort
I've messed with this with when/2 and var/1/nonvar/1 and haven't been able to solve that little problem.

Setting some order for prolog expressions

I've got a rule in my Prolog program called blanket(X,Y) which checks if X is in a certain kind of set of Y which consists of:
Y's parents
Y's children
Y's coparents
I've defined it as follows :
blanket(Y,X) :- different(Y,X),parent(Y,X);child(Y,X);coparent(Y,X).
However, this doesn't work as I expect. It correctly identifies X's parents, children, and coparents (if any) but it lists itself as both a parent and a coparent, which I do not want. Is it possible to set some kind of order, so that the different(Y,X) evaluates first and independently? I tried something like : different(Y,X),(parent(Y,X);child(Y,X);coparent(Y,X))., of course, but that yields a syntax error as I"m still quite unfamiliar with the language.
Any suggestions would be greatly appreciated.
EDIT: Here are the child, different, and coparent relations:
child(X,Y) :- parent(Y,X).
different(X,Y) :- not(X == Y).
coparent(Y,X) :- parent(Y,Z),parent(X,Z).
For completeness.
blanket(Y,X) :- different(Y,X), parent(Y,X).
blanket(Y,X) :- different(Y,X), child(Y,X).
blanket(Y,X) :- different(Y,X), coparent(Y,X).
The problen is your definition of coparent. It is the statement that allows return itself as a valid result.
I suggest you redefine it, by example as:
coparent(Y,X) :- parent(Y,Z),parent(X,Z), X \= Y.
in this way, you can simply:
blanket(Y,X) :-parent(Y,X);child(Y,X);coparent(Y,X).
Of course, you can keep definition of "coparent" and only modify blanket as:
blanket(Y,X) :-parent(Y,X);child(Y,X);(coparent(Y,X), X\=Y).

How to say if an element belongs to a list in Prolog?

I have this simple program that checks if an X element belongs to a list:
member2(X, [X|_]).
member2(X,[_|T]):- member2(X,T).
I'm trying to write it in an extended form (because in the previous way the behavior is not so clear). So I have write it in the following way:
member2(X, [X|_]).
member2(X,Y):- Y = [_|T],
member2(X,T).
So the meaning is more clear:
I have one fact that represent the base case (the X element belongs to the list if it is in the head of the list).
The rule say that I have to prove two things:
1) Y = [_|T]. This is true because the anonymous variable _ unifies with anything.
2) It recursively search the element X in the tail list.
Ok, I think my reasoning is correct but this second version of the program don't work! I think that maybe the problem could be in the Y = [_|T] section
your program is fine, in both forms. Here yet another way to (re)write it
member2(X, [Y|Ys]) :-
X = Y ; member2(X, Ys).
I guess the textbook example of checking for a member is:
member_check(X, [X|Tail]). % or [X|_] to avoid the warning
member_check(X, [Y|Tail]) :- X \= Y, member_check(X, Tail).
which would probably be clearer than your second attempt?

prolog: built-in or other method to use function-like return values

I'm trying to let Prolog instantiate a variable to the opposite key of a public/private key pair, if that is even possible.
So I basically have:
publicKey(k_c).
privateKey(k_c-1).
keyPair(k_c,k_c-1).
Given the nature of Prolog I don't think you could manage something like
inverseOf(X) :-
(keyPair(X,Y), return(Y),!);(keyPair(Y,X),return(Y),!).
Why I want/need this?
I have a rule
init(Init_1, Init_2,Init_3)
and I want to check for something like
Init_3 == inverseOf(Init_2).
Any ideas?
Define
inverseOf(X, Y):- keyPair(X,Y), !.
inverseOf(X, Y):- keyPair(Y,X), !.
and then use
inverseOf(Init_2, Init_3).
With something like this defined:
keypair(pub1, priv1).
keypair(pub2, priv2).
keypair(pub3, priv3).
keymatch(A, B) :- keypair(A, B).
keymatch(A, B) :- keypair(B, A).
You could ask things like:
keymatch(pub1, X).
keymatch(priv2, X).
keymatch(priv3, pub3).
An aside...
Prolog does not have functions; you can't say something like Y = f(X) in Prolog (actually you can, but it doesn't do what you'd expect if you're coming from a C/Java/Python/etc background.
To implement the functionality of Y = f(X) in Prolog, you would do something like this
f(X, Y) :- Y is X + 1.
and invoke it like this
f(3, Y).
Y would evaluate to the value 4.

Resources