writing rules in prolog - prolog

I am learning Prolog and would just like to check myself:
I think this question is very basic but I am just beginning.
father(X,Y)
mother(X,Y)
male(X)
female(X)
parent(X,Y)
diff(X,Y)
To write a clause for is_mother(X) is this correct?
is_mother(X):- female(X), parent(X,Y).
Thank you

is_mother(X) :- female(X), parent(X,Y).
This is technically correct in that it says, X is a mother if X is female, and X is the parent of someone (Y). In this definition, Prolog will give you a warning about Y being a "singleton" variable since you don't use its value. To avoid that warning, you can use _ or a name that starts with _ to indicate a variable whose value you don't care about and Prolog won't warn that you're not using:
is_mother(X) :- female(X), parent(X,_).
The terms female(X) and parent(X,_) assume that you have either predicates female(X) and parent(X,Y) or you have facts, such as (for example) female(sally). where sally is an "atom" (a constant in Prolog), and/or parent(sally, tom).

Related

How to print all females in prolog if my facts only contains male property

Lets suppose my db.pl file consists of only
male(Oliver)
male(james)
male(sam)
female(X) :- \+ male(X)
Now if I query,
?- male(X).
Then this will successfully return all the males.
But if I query,
?- female(X)
Then this will not. However, if I put a name in the female predicate, it correctly gives the output as yes/no.
What am I missing here? How do I get the list of all females? Or basically list of "not male".
I thought I'd give a proper answer as well. As mentioned in the comments, the fact male(Oliver). contains the variable Oliver such that e.g. also male(catherine_the_great) succeeds. But fixing this mistake will not solve the problem. Suppose we fix the facts for male and define female as above:
male(oliver)
male(james)
male(sam)
female(X) :-
\+ male(X).
Then we can not derive male(catherine_the_great) anymore but female(catherine_the_great) succeeds:
?- male(catherine_the_great).
false.
?- female(catherine_the_great).
true.
Unfortunately, by this definition, a hamburger is also female:
?- female(hamburger).
true.
What's even worse is, when we ask if there exists someone female (at all!), we get no as an answer:
?- female(X).
false.
The reason for this is that \+ is not classical negation(*) but what is called weak negation / negation as failure. \+ male(X) is true if there is no X such that male(X) is derivable. But as soon as male/1 succeeds with any solution (e.g. male(oliver)), the negation fails. In such cases the substitution male(X) is not proper substiution for female(X) but how are we supposed to get a list of all women? A possible solution is a list of persons of which we define male/female as subsets:
person(oliver).
person(james).
person(sam).
person(jackie).
person(selma).
male(oliver).
male(james).
male(sam).
female(X) :-
person(X),
\+ male(X).
When we query a list of all women, we now get:
?- female(X).
X = jackie ;
X = selma.
I'd rather use a separate predicate listing women though because it is less error prone when adding new persons.
In general, negation as failure is rarely safe. Two rules of thumb i have for myself:
whenever \+ p(X) appears as a goal, it is fully instantiated (a ground term). In our case, this is what person assures.
p(X) terminates for every ground term X. This assures termination of the negation as well.
(*) in classical logic, the rule of generalization female(jackie) → ∃X female(X) holds but here we can not derive ∃X female(X) despite being able to derive female(jackie).

prolog family tree locating cousins

The Cousin Explainer
Write a program that when given a person of reference and a degree the program can tell me all of the nth degree cousins that person has. I've started by writing my facts: male/1 female/1 and child/2 these are populated with the names of my family members. I then began writing rules for cousins I figured id write a different rule for every degree so only up to the third cousins. The problems I'm having are as follows.
firstCousin_of(X,Y):-child(X,Z1),child(Y,Z2),child(Z1,Z),child(Z2,Z). I have this to find a first cousin but the 2nd cousin is more complicated which makes me think there has gotta be a way to do this recursively.
I need the rule, all_cousins(Person, Degree, ListOfCousins), which after figuring out all of the nth degree cousins edits a list of all cousins to only include those specific nth degree cousins. I'm used to imperative languages and all i can think about with this is how do I even convey to the rule which people to remove from the list from one rule to another.
lastly I have a rule, all_cousinsRemoved(Person, Degree, removed(Number, Direction), ListOfCousins) that I don't even know where to start with but ill need the all_cousins rule for this one because it does the same thing but also only includes cousins in the edited lists w=that were removed nth times either up or down.
The best solutions is make a several rules that call other rules, here an example
male(dicky).
male(randy).
male(mike).
male(don).
male(elmer).
female(anne).
female(rosie).
female(esther).
female(mildred).
female(greatgramma).
male(blair).
male(god).
female(god).
parent(don,randy).
parent(don,mike).
parent(don,anne).
parent(rosie,randy).
parent(rosie,mike).
parent(rosie,anne).
parent(elmer,don).
parent(mildred,don).
parent(esther,rosie).
parent(esther,dicky).
parent(greatgramma,esther).
parent(randy,blair).
male(mel).
male(teo).
parent(melsr,mel).
parent(melsr,teo).
american(anne).
american(X) :- ancestor(X,anne).
american(X) :- ancestor(anne,X).
relation(X,Y) :- ancestor(A,X), ancestor(A,Y).
father(X,Y) :- male(X),parent(X,Y).
father(god, _) :- male(god).
mother(X,Y) :- female(X),parent(X,Y).
son(X,Y) :- male(X),parent(Y,X).
daughter(X,Y) :- female(X),parent(Y,X).
grandfather(X,Y) :- male(X),parent(X,Somebody),parent(Somebody,Y).
aunt(X,Y) :- female(X),sister(X,Mom),mother(Mom,Y).
aunt(X,Y) :- female(X),sister(X,Dad),father(Dad,Y).
sister(X,Y) :- female(X),parent(Par,X),parent(Par,Y), X \= Y.
uncle(X,Y) :- brother(X,Par),parent(Par,Y).
cousin(X,Y) :- uncle(Unc , X),father(Unc,Y).
ancestor(X,Y) :- parent(X,Y).
ancestor(X,Y) :- parent(X,Somebody),ancestor(Somebody,Y).
brother(X,Y) :- male(X),parent(Somebody,X),parent(Somebody,Y), X \= Y.
Retrived from this repository

Uncle or Aunt without sibling fact

I'm wondering how would I be able to call a nephew or niece in a family tree without using a sibling fact for prolog. I can't figure out a way to do it by calling the uncle directly.
For example:
parent(elli, lisa).
parent(kelly, lisa).
parent(ben, claire).
parent(lisa, claire).
grandparent(X, Y) :- parent(X, Z), parent(Z, Y).
Since ellie or kelly is ben's niece, I have the rule that when called by grandparent(X, claire). will give elli and kelly as the grandchild of claire. How would I make a rule to be able to call niece(ben, X). so it'll list all of ben's niece. I can't figure out a way to do it with only the parent fact, the only way of doing it would be to include a sibling fact but is there a way to do it without making a sibling fact?
I'm very new to prolog, literally like a week ago so please excuse me if I don't understand it that well.
brother(X, Y) :- male(X), parent(X, Z), parent(Y, Z), X \= Y.
uncle(X, Y) :- brother(X, Z), parent(Y, Z).

Logics in Prolog

How can I express next 3 sentences in Prolog?
All summers are warm. If it not summer, then it is winter. Now it is winter.
Nice question.
As #larsman (well, #FredFoo now, I think) rightly said, can be a large thema. And his answer is very good indeed.
As your question could be driven by necessity of a custom language (one of main Prolog' uses), here I propose the syntax sugar for a dummy DSL (what that's means it's totally empty now...)
:- op(500, fx, all).
:- op(500, fx, now).
:- op(600, xfx, are).
:- op(700, fx, if).
:- op(399, fx, it).
:- op(398, fx, is).
:- op(397, fx, not).
:- op(701, xfx, then).
all summers are warm.
if it is not summer then it is winter.
now it is winter.
SWI-Prolog is kind enough to make red those op that get stored, i.e. can be queried easily. These are the higher precedence words declared: i.e. are,then,now.
?- now X.
X = it is winter.
How to represent this depends on what inferences you want to make. One of the simplest ways is
warm :- summer.
winter.
The "if not summer then winter" rule does not actually allow you to make any useful inferences, so you could just as well skip it. If you were to include it, it might be something like
winter :- \+ summer.
but since negation in Prolog is negation as failure, this might not do what you think it does if you expect the semantics of vanilla propositional logic.
winter(now).
warm(X) :- summer(X).
summer(X) :- \+ winter(X).
winter(X) :- \+ summer(X).
Would be one of the ways to do this.
In action:
6 ?- summer(now).
false.
7 ?- summer(tomorrow).
ERROR: Out of local stack
8 ?- warm(now).
false.
Here a solution without using negation, instead the universe of seasons is
specified.
season(summer).
season(winter).
now(winter).
warm(S) :-
season(S),
S = summer.
Some example queries:
?- now(S).
S = winter ;
false.
?- now(S), warm(S).
false.
?- warm(S).
S = summer ;
false.

How to negate in Prolog

I'm new to PROLOG and am at the very beginning of the exercises on this page. Given the rules parent(X, Y) and male(X), I'm trying to define a rule mother(X, Y) as
mother(X, Y) :-
not(male(X)),
parent(X, Y).
However, in GNU Prolog I get the following error:
| ?- mother(lina, julia).
uncaught exception: error(existence_error(procedure,not/1),mother/2)
| ?-
\+/1 is the ISO Prolog predicate to "negate". Note that "negate" means here not provable at that point.
You can refer to this excellent answer by #false for more on the subject
The solution is actually in the exercise file on that page:
female(X) :- \+ male(X).
As #Mog said, negation is the unary \+ operator.

Resources