Define a new infix operator is_bigger to compare the size of two animals mentioned in the facts
animals(500,xfx,is_bigger).
Is this the solution?
To define a new operator, you need to use the ISO built-in predicate op/3:
:- op(500, xfx, is_bigger_than).
elephant is_bigger_than horse.
Query:
?- X is_bigger_than Y.
X = elephant,
Y = horse.
Related
I have to create family relations in Prolog for an assignment and I stumbled upon this problem.
man(john).
woman(lisa).
married(john,lisa).
?- married(john,X).
X = lisa.
?- married(X,john).
false.
How to make this predicate work in two ways?
If john is married to lisa, then lisa is married to john.
For facts I can only use gender, parent, and married:
man(john).
woman(lisa).
parent(john,steve).
parent(lisa,steve).
married(john,lisa).
That requirement makes this solution unusable for me. I can't just add relation wife(lisa,john). because I have to define wife, husband etc. by myself, like.
wife(X,Y) :- woman(X),married(X,Y).
Instead of trying to make married/2 bidirectional, you could define your predicate wife/2 accordingly. If the first argument of married/2 is always the husband and the second always the wife, just flip the arguments of the second goal:
wife(X,Y) :-
woman(X),
married(Y,X). % <- changed to Y,X instead of X,Y
With your given facts this yields the desired result:
?- wife(X,Y).
X = lisa,
Y = john.
If your facts also include pairs the other way around, e.g.:
woman(ann).
man(anton).
married(ann, anton).
you can include a second rule (namely your original rule) for wife/2 to deal with such pairs as well:
wife(X,Y) :-
woman(X),
married(Y,X).
wife(X,Y) :- % <- new rule
woman(X),
married(X,Y).
With the additional rule and facts the above query now yields:
?- wife(X,Y).
X = lisa,
Y = john ;
X = ann,
Y = anton.
If you can't add helper relation (it sounds like homework exercise), try to use predicate #< which operates on the "Standard Order of Terms":
married(A,B) :- A #< B, married(B,A).
Note, however, that this solution brings also some negative aspects (please read this answer).
male(jerry).
male(stuart).
male(warren).
male(peter).
female(kather).
female(maryalice).
female(ann).
brother(jerry,stuart).
brother(jerry,kather).
brother(peter, warren).
sister(ann, maryalice).
sister(kather,jerry).
parent_of(warren,jerry).
parent_of(maryalice,jerry).
I was given the facts above and I need to define a rule using the predicate parent_of. Yes, it is the same predicate as the above facts defined by parent_of.
Assume I have a sibling(X, Y) rule that will return all the correct sibling pairs.
I write my parent_of(X, Y) rule as parent_of(X, Y) :- parent_of(X, A), sibling(A, Y).
However, this implementation will lead me to an infinity loop.
Is there a way to define the rule parent_of(X, Y) such that it will return
(warren, jerry),
(warren, stuart),
(warren, kather),
(maryalice, jerry),
(maryalice, stuart),
(maryalice, kather)
I also tried
parent_of(X, Y) :-
parent_of(X, jerry),
brother(jerry, Y).
I can get the correct answers by this way but it ended up in "Out of local stack" error. Besides that, I don't think the rule is fine as I hard coded it.
I have seen suggestions like change the rule name to something else such as another_parent_of(X, Y). It does solve the problem, but it is a requirement for me to define it using the same predicate.
Any help is greatly appreciated.
EDITED
The intention of this exercise is to write rules such that you can complete this family tree, though only minimal facts are given. As you can see, it only states that Warren is the father of Jerry, and from brother and sister facts, we know Jerry is the brother of Stuart and Kather. So I will have a rule, parent_of(X, Y) to deduce Warren is also the father of Stuart and Kather, though this was not stated in the facts above.
The main concern is how can I write my parent_of(X, Y) rule to avoid it getting into infinite loop.
I do not understand why you need to use parent_of in the definition of sibling. Why you no just write:
sibling(X, Y) :-
parent_of(Parent, X),
parent_of(Parent, Y).
I also don't understand the logic of the facts that you are given. You have male and female, but you also have brother and sister; why not define brother and sister in terms of "brother is a male sibling" and "sister is a female sibling"? I already show above how to define "siblings have same parent".
Anyway, this is really old tired question, it is very amazing how many times "Prolog family tree" has been regurgitated.
the cow the old cow she is dead
it sleeps well the horned head
we poor lads tis our turn now
to hear such tunes as killed the cow
I cannot see a way to directly solve your problem. But if your Prolog offers tabling, here is an easy way:
:- use_module(library(tabling)).
...
:- table parent_of/2.
parent_of(warren,jerry).
parent_of(maryalice,jerry).
parent_of(X, Y) :- parent_of(X, A), sibling(A, Y).
...
?- parent_of(X,Y).
X = warren,
Y = stuart ;
X = warren,
Y = jerry ;
X = warren,
Y = kather ;
X = maryalice,
Y = stuart ;
X = maryalice,
Y = jerry ;
X = maryalice,
Y = kather.
I'm new to Prolog. Is it possible to "declare" a list as a fact in Prolog, and then access it easily? I'm working on a family-tree type problem. To start, I would like to declare a bunch of males as belonging to a list of males. I then would like to be able to query if a particular person is a male. Here is the code I've written so far:
% ------------------------------------------------------------------------- %
% Facts:
males([john, joseph, aaron, peter, paul, mark, ben, adam, daniel]).
% ------------------------------------------------------------------------- %
% Rules:
% Member of a List
member(X, [X|_]).
member(X, [_|T]) :- member(X, T).
male(X) :- member(X, males).
However, my output is not as expected:
21 ?- male(john).
false.
I know my member() rules are working, since I can produce the following result:
23 ?- member(john, [peter, paul, john]).
true
Can anyone point me in the right direction? Thank you in advance.
The usual proper way to do this in Prolog would be to declare your list as a table of facts:
male(john).
male(joseph).
% etc
If you do it like this, you have already defined your male/1 and can query it either like this:
?- male(joseph).
true.
Or like this:
?- male(M).
M = john ;
M = joseph ;
% etc
You can start with Prolog by reading through the first chapter of "Learn Prolog Now!". Its first example is exactly the same as your problem.
I'm not an expert in prolog but I know a solution to this (could be not the only one)
male(X) :- males(Y), member(X, Y)
The way I understand it is that predicates doesn't return variables, they assign values to the parameters given, so Y now have been assigned the array of males and now you can look for X in Y
I have compound terms that can have a number inside the braces.
For example: qpowieipq(5),lsjdlasa(15) or lkjlk. I got it from the database (like my_list([rxclk,rxer,rxdv,rxd(0),rxd(1),rxd(2),crs,col,txen,txd(0),txd(1),txd(2),txd(3)]).).
How can I get the value of the number inside the braces?
For example:
my_function(qpowieipq(5), X).
X=5.
my_function(lsjdlasa(15), X).
X=15.
my_function(lkjlk, X).
false
I am using SWI Prolog.
You can use (=..)/2 and pattern matching to deconstruct Prolog's compound terms. For instance
?- a =.. X.
X = [a].
?- a(1) =.. X.
X = [a, 1].
So, tentatively
my_function(T, V) :- T =.. [_,V], number(V).
This will work with any ISO compliant Prolog processor.
I have some facts like:
person(david).
student(david).
I need to find the functors that david is in. So I need to post a query like:
some_query(david)
and I need the answers to be
person and
student.
How can I do this in Prolog?
Thank you!
This is not possible without resorting to some special predicates provided by the interpreter, i.e., this is not pure Prolog anymore, but for swi-prolog this works:
findFor(Const, X) :-
current_predicate(X, Z),
not(predicate_property(Z, built_in)),
Z =.. [_, _],
Y =.. [X, Const],
call(Y).
then just call: findFor(david, X), or if you want all answers in one query use findAll.