Convert statements into prolog code - prolog

Hey
I 'm trying to convert the following statements into prolog code, but I'm not sure if I did it correctly.
1-everybody who respects himself is respected by others:
respects(x,respects(x)) :- respects(y,x)).
2-john respects herself:
respectsherself(john).
respects(john,respectsherself(john)).
Thanks

In prolog variables must start with a capital letter so look out for that.
Everybody who respects himself is respected by others. I think you need some basic facts such as who respects who. Then you can declare a rule that says X is respected by others is implied by X respecting Himself.
respects(john, mary). %john respects mary
respects(john, john). %john respects himself
respects(X, Y) :- respectedbyothers(Y). %X respects Y if Y is respected by others
respectedbyothers(X):-respects(X, X).

An optimization:
%respects(A,B) means A is respected by B
respects(john,john).
respects(X,_):-respects(X,X).
?
Don't you just love prolog :)

Related

What am I missing about equality and unification in Prolog?

I'm working through Clocksin and Mellish to try and finally go beyond just dabbling in Prolog. FWIW, I'm running SWI-Prolog:
SWI-Prolog version 7.2.3 for x86_64-linux
Anyway, I implemented a diff/2 predicate as part of exercise 1.4. The predicate is very simple:
diff(X,Y) :- X \== Y.
And it works when used in the sister_of predicate, like this:
sister_of(X,Y) :-
female(X),
diff(X,Y),
parents(X, Mum, Dad ),
parents(Y, Mum, Dad ).
in that, assuming the necessary additional facts, doing this:
?- sister_of(alice,alice).
returns false as expected. But here's the rub. If I do this instead:
?- sister_of(alice, Who).
(again, given the additional facts necessary)
I get
Who = edward ;
Who = alice;
false
Even though, as already shown, the sister_of predicate does not treat alice as her own sister.
On the other hand, if I use the SWI provided dif/2 predicate, then everything works the way I would naively expect.
Can anyone explain why this is happening this way, and why my diff implementation doesn't work the way I'm expecting, in the case where I ask for additional unifications from that query?
The entire source file I'm working with can be found here
Any help is much appreciated.
As you note, the problem stems from the interplay between equality (or rather, inequality) and unification. Observe that in your definition of sister_of, you first find a candidate value for X, then try to constrain Y to be different, but Y is still an uninstantiated logic variable and the check is always going to succeed, like diff(alice, Y) will. The following constraints, including the last one that gives a concrete value to Y, come too late.
In general, what you need to do is ensure that by the time you get to the inequality check all variables are instantiated. Negation is a non-logical feature of Prolog and therefore potentially dangerous, but checking whether two ground terms are not equal is safe.

Swi-Prolog: No permission to modify static procedure `(;)/2'

Hi :) Beginner to Prolog.
I have this code:
dog(rex).
owns(bill,rex).
animallover(X):-owns(X,Y),dog(Y).
not(beat(X,Y)):-animallover(X),isAnimal(Y).
beat(bill,tom);beat(bull,tom).
iscat(tom).
isAnimal(X):-iscat(X).
This yields the error: No permission to modify static procedure `(;)/2'
What's wrong there?
Thanks for your help.
dog(rex).
owns(bill,rex).
animallover(X):-owns(X,Y),dog(Y).
notbeat(X,Y):-animallover(X),isAnimal(Y).
not(notbeat(bill,tom),notbeat(bull,tom)).
iscat(tom).
isAnimal(X):-iscat(X).
This solves the problem. But we want to answer the question "Who hit Tom?"
That way we can only ask
?- nothit(X,tom).
and this would yield bill.
So how can we change the code so we can ask who did hit Tom?
The source of your problem is some code that would, in a lesser language, produce a syntax error, but which is syntactically valid but definitely meaningless Prolog.
This part of your code is totally fine:
dog(rex).
owns(bill, rex).
animallover(X) :- owns(X, Y), dog(Y).
Whitespace is free. :)
This is your first problem:
not(beat(X,Y)) :- animallover(X), isAnimal(Y).
I'm not sure what you're trying to say here because I've been doing Prolog too long. But what you are saying here, stated a little differently, is this:
not(Q) :- Q = beat(X, Y), ...
In other words, the procedure you are defining here is not/1, rather than anything to do with beat/2. You've got too much stuff in the head. This is kind of an unusual problem for a beginner; usually people with exposure to other languages would make the error of doing too much assignment on the right side of :- rather than the left side.
In any case, another way to read Q :- P is, "to prove Q, I must first prove P." That's how Prolog thinks about it. Or, "if P, then I can conclude Q." So, you're teaching Prolog how to make a conclusion called not, which is almost certainly not what you mean.
Now, on to your next line, where the error occurs:
beat(bill, tom); beat(bull, tom).
Prolog deals in what are called Horn clauses. The generic Horn clause looks like Q :- P, but if you omit :- P, what you get is usually called a fact. In this case, the entire thing you have on that line is one fact. The head of that expression turns out to be ;, so what you've actually written is this:
A ; B :- A = beat(bill, tom), B = beat(bull, tom).
You're trying to redefine ;/2 here, in essence, and Prolog is not allowing that because ; is too important. What you probably meant here was just a period separating two facts: beat(bill, tom). beat(bull, tom)..
I hope this helps get you over the hump.
In the line
beat(bill,tom);beat(bull,tom).
you seem to mean "Bill beat Tom or Bull beat Tom".
But by Prolog's rules you are instead trying to redefine ;, which isn't allowed, and you can't write "Bill beat Tom or Bull beat Tom" as a fact.

How to define a user defined predicate in Prolog

I want to write the following constraint in Prolog, is it possible?
C1(x, y) : isSU(x) ∧ isSU(y)
note that isSU is a user defined predicate which reads a configuration file, and checks whether its input parameter (here x or y) has a certain condition or not.
Actually my problem is that, I don't know how to define a user defined predicate in Prolog. The other thing is that I don't know how to use universal and existential quantifiers in a rule in Prolog.
Thanks for your answer.
Ali Davoudian
In SWI-Prolog your constraint would be written that way:
c1(X, Y) :- isSU(X), isSU(Y).
And about the rest I would recommend reading a book. Here is good list of free books about Prolog programming: https://stackoverflow.com/tags/prolog/info

evaluating possible situations using prolog

I am trying to see the possible situations for the following facts.
don likes cain
bob does not like don
cain does not like aron
nobody likes someone who does not like him
aron likes everyone who likes bob
don likes everyone bob likes
everybody likes somebody
I have just started learning prolog and I am trying to implement this in prolog and see how many possible situations arise. I scanned through few prolog threads here and I am also using the book "Learn prolog now" . So here is my best attempt to come up with the code.
likes(don, cain).
likes(aron,W):- likes(W,bob).
likes(don,M):- likes(bob,M).
(likes(aron,aron);likes(aron,bob));(likes(aron,cain);likes(aron,don)).
(likes(bob,aron);likes(bob,bob));(likes(bob,cain);likes(bob,don)).
(likes(cain,aron);likes(cain,bob));(likes(cain,cain);likes(cain,don)).
(likes(don,aron);likes(don,bob));(likes(don,cain);likes(don,don)).
not(likes(bob,don)).
not(likes(cain,aron)).
not(likes(Y,X)) :- not(likes(X,Y)).
When I run this in swipl compiler in Ubuntu Linux (which is in VirtualBox inside winxp), I get following errors
?- [test].
ERROR: /home/test.pl:11:
'$record_clause'/2: No permission to modify static_procedure `(;)/2'
ERROR: /home/test.pl:13:
'$record_clause'/2: No permission to modify static_procedure `(;)/2'
ERROR: /home/test.pl:15:
'$record_clause'/2: No permission to modify static_procedure `(;)/2'
ERROR: /home/test.pl:17:
'$record_clause'/2: No permission to modify static_procedure `(;)/2'
% test compiled 0.00 sec, 1,616 bytes
true.
So can you help me with this...... I have made use of not as a predicate here, some threads on the net seem to mention it.
In Prolog we have a fairly natural representation of what's true, but when faced with negative information (say negation), we must adapt our intuition to the restricted computation model that Prolog offer.
In particular, Prolog semantic being based on closed world assumption, we could be tempted to omit as irrelevant proposition like bob does not like don, because this just states the absence of the positive clause 'bob likes don'. Such absence is indeed 'absorbed' in Prolog proof search, and formalized by a 'procedural' definition of not (the only available in Prolog, but with an operator less reminiscent of 'human' interpretation, i.e. \+ means not):
\+ X :- call(X), !, fail.
\+ X.
See this page for further explanation about.
All this introductory to say that I would introduce a not_like/2 to represent explicitly the 'negative' knowledge. Syntactically we get:
likes(don, cain).
not_likes(bob, don).
not_likes(cain, aron).
not_likes(X, Y) :- \+ likes(Y, X).
likes(aron, X) :- likes(X, bob).
likes(don, X) :- likes(bob, X).
likes(_, _).
Now those statements make sense? Prolog takes the viewpoint of a practical approach to logic programming, and it run queries against such knowledge, that make perfectly sense for some programming task...
edit suggested by comment, I think that instead of likes(_,_)., a better code for everybody likes somebody should be
likes(X, Y) :- \+ not_likes(X, Y).
This is justified by the last fact, but standalone it not allows to infer not_likes(cain, aron).

Reverse lookup in Prolog? (how do I find everything that is true about X?)

So, let's say I have the following in a Prolog database:
person(john).
person(mary).
happy(john).
It is clear to that if I want to list all people, I can type:
person(X).
But, what if I want to find all the things that are true about john? I cannot do:
X(john).
But the effect I would like is to be able to put in "john" and get back "person" and "happy".
There is clearly another way I could store my information:
is(person, john).
is(person, mary).
is(happy, john).
And then, I can do:
is(X, john).
But I lose some expressiveness here. I really would like to be able to do something like:
X(john).
Any ideas?
Thanks!
Parameterizing a query over predicates (as in finding ∀x over x(...)) is not usually possible natively in PROLOG, as this sort of thing is a second- (or, higher)-order logic operation, whereas PROLOG is based on first-order logic.
There are, however, descriptions of how implementations of higher-order logic functions in PROLOG are possible, at least to a limited extent - there are real uses for such functionality. See The Art Of Prolog, Chapter 16, and Higher-order logic programming in Prolog by Lee Naish.
Hm, from my experience, that's not the typical use case of Prolog. If you want to enumerate all "facts" about John, you would first have to define them as terms, and encode their arity. Then you can use call/N and go down the rabbit hole another notch (from memory with the help of GNU Prolog):
relation(1,person).
relation(2,married).
person(john).
married(john,mary).
? relation(1,X), call(X,john).
X = person
| ?- relation(2,X),call(X,john,Y).
X = married
Y = mary
Note that using call has many interesting issues and potential for runtime errors.
This is an approximation:
all_predicates(Term) :-
current_predicate(_, Pred), %% match Pred to any currently defined predicate
\+ predicate_property(Pred, built_in), %% filter out the built-in predicates
functor(Pred, Name, 1), %% check that Pred has 1 argument and match Name to its name
Goal =.. [Name, Term], %% construct the goal Name(Term)
call(Goal). %% Note that if Pred has side effects, they will happen.

Resources