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

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.

Related

Binary logic in prolog

I want to solve following problem using inference making power of prolog.
One day, 3 persons, a, b, c were caught by police at the crime spot. When police settled interrogating them:
i) a says I am innocent
ii) b says a is criminal
iii) c says I am innocent.
Its known that
i) Exactly one person speaks true.
ii) Exactly one criminal is there.
Who is criminal?
To model above problem in First Order logic:
Consider c/1 is a predicate returns true when argument is Criminal
we can write:
(not(c(a)),c(c)) ; (c(c),c(a)).
c(a); c(b); c(c).
(not(c(a)),not(c(b))) ; (not(c(a)),not(c(c))) ; (not(c(b)),not(c(c))).
After modelling above statements in prolog, I will query:
?-c(X).
it should return:
X=c.
But error I got:
"No permission to modify static procedure `(;)/2'"
Since PROLOG does indeed work with Horn clauses, you'll need things of form head :- tail, reading :- as "if."
solve(Solution) :- ...
%With a Solution looking something like:
% solve(a(truth,innocent),b(false,criminal),c(false,innocent)).
To use the generate and test method, which is a common and reasonable way to solve this, you'd do something like this:
solve(Solution) :-
Solution = [a(_,_),b(_,_),c(_,_)],
generate(Solution),
validate(Solution).
generate should give you a well-formed Solution, that is, one having all the variables filled in with values that make some kind of sense (that is, false, true, criminal, innocent).
validate should ensure that the Solution matches the constraints you gave.
solve only completes when one of generate's solutions makes it past validate's constraints.
For an introduction to the generate and test method, see this tutorial.
But if you're writing code that isn't Horn clauses, you might need a tutorial on writing PROLOG functions (OK, relations), like this one.

Prolog: Code Generation

What's the most idiomatic approach to output prolog code from a prolog program (as a side effect)?
For instance, in a simple case, I might want to write a Program that, given a text input, yields another Prolog program representing the text as a directed graph.
I understand this question is somewhat vague, but I've resigned to consulting Stackoverflow after failing to find a satisfying answer in the available Prolog Meta-Programming literature, which mostly covers applications of meta-circular interpreters.
If you feel this question might be better articulated some other way, please edit it or leave a comment.
The most idiomatic way is always to stay pure and avoid side effects.
Let the toplevel do the writing for you!
To generate a Prolog program, you define a relation that says for example:
program(P) :- ...
and then states, in terms of logical relations, what holds about P.
For example:
program(P) :-
P = ( Head :- Body ),
Head = head(A, B),
Body = body(A, B).
Example query and answer:
?- program(P).
P = (head(_G261, _G262):-body(_G261, _G262)).
So, there's your program, produced in a pure way.
If you want to write it, use portray_clause/1:
?- program(P), portray_clause(P).
head(A, B) :-
body(A, B).
...
This can be useful in a failure driven loop, to produce many programs automatically.
writeq/1 (or format('~q', [...])) produces output that can be read back. Usually you need also to put a full stop after a clause body. For instance, try
?- A_Clause = (X is 1+Y, write('X is '), write(X), nl), format('~q.~n', [A_Clause]).
Readability of code suffers from loosing variables 'nice names', but the functionality is there...
edit
as noted by #false, a space before the dot will avoid a bug in case the output term would finish with a dot

Prolog - Rules are correct, but not outputting the way it's supposed to?

Clue
Four guests (Colonel Mustard, Professor Plum, Miss Scarlett, Ms. Green) attend a dinner party at the home of Mr. Boddy. Suddenly, the lights go out! When they come back, Mr Boddy lies dead in the middle of the table. Everyone is a suspect. Upon further examination, the following facts come to light:
Mr Boddy was having an affair with Ms. Green.
Professor Plum is married to Ms. Green.
Mr. Boddy was very rich.
Colonel Mustard is very greedy.
Miss Scarlett was also having an affair with Mr. Boddy.
There are two possible motives for the murder:
Hatred: Someone hates someone else if that other person is having an affair with his/her spouse.
Greed: Someone is willing to commit murder if they are greedy and not rich, and the victim is rich.
Part A: Write the above facts and rules in your Prolog program. Use the following names for the people: colMustard, profPlum, missScarlet, msGreen, mrBoddy. Be careful about how you encode (or don’t encode) symmetric relationships like marriage - you don’t want infinite loops! married(X,Y) :- married(Y,X) % INFINITE LOOP
?-suspect(Killer,mrBoddy)
Killer = suspect_name_1
Killer = suspect_name_2
etc.
Part B: Write a predicate, suspect/2, that determines who the suspects may be, i.e. who had a motive.
?-suspect(Killer,mrBoddy)
Killer = unique_suspect.
Part C: Add a single factto your database that will result in there being a unique suspect.
Clearly indicate this line in your source comments so that it can be removed/added for
grading.
?-suspect(Killer,mrBoddy)
Killer = unique_suspect.
Whenever I type in
suspect(Killer,mrBoddy).
I get
suspect(Killer,mrBoddy).
Killer = profPlum
I'm missing
Killer = colMustard.
Here's my source.
%8) Clue
%facts
affair(mrBoddy,msGreen).
affair(missScarlett, mrBoddy).
affair(X,Y) :- affair(X,Y), affair(Y,X).
married(profPlum, msGreen).
married(X,Y) :- married(X,Y), married(Y,X).
rich(mrBoddy).
greedy(colMustard).
%rules
hate(X,Y) :- married(X,Spouse), affair(Y,Spouse).
greed(X,Y) :- greedy(X), not(rich(X)), rich(Y).
%suspect
suspect(X,Y):- hate(X,Y).
suspect(X,Y):- greed(X,Y).
There are two kinds of problems with your program. One is on the procedural level: you observed that Prolog loops; the other is on the logical level — Prolog people call this rather the declarative level. Since the first annoying thing is this endless loop, let's first narrow that down. Actually we get:
?- suspect(Killer,mrBoddy).
Killer = profPlum ;
ERROR: Out of local stack
You have now several options to narrow down this problem. Either, go with the other answer and call up a tracer. While the tracer might show you the actual culprit it might very well intersperse it with many irrelevant steps. So many that your mind will overflow.
The other option is to manually modify your program by adding goals false into your program. I will add as many false goals as I can while still getting a loop. The big advantage is that this way you will see in your source the actual culprit (or to be more precise one of potentially many such culprits).1 After trying a bit, this is what I got as failure-slice:
?- suspect(Killer,mrBoddy), false.
married(profPlum, msGreen) :- false.
married(X,Y) :- married(X,Y), false, married(Y,X).
hate(X,Y) :- married(X,Spouse), false, affair(Y,Spouse).
suspect(X,Y):- hate(X,Y), false.
suspect(X,Y):- false, greed(X,Y).
All remaining parts of your program were irrelevant, that is, they are no longer used. So essentially the rule
married(X,Y) :- married(X,Y), married(Y,X).
is the culprit.
Now, for the declarative part of it. What does this rule mean anyway? To understand it, I will interpret :- as an implication. So provided what is written on the right-hand side is true, we conclude what is written on the left-hand side. In this case:
Provided X is married to Y and Y is married to X
we can conclude that
X is married to Y.
This conclusion concluded what we have assumed to be true anyway. So it does not define anything new, logically. You can just remove the rule to get same results — declaratively. So married(profPlum, msGreen) holds but married(msGreen, profPlum) does not. In other words, your rules are not correct, as you claim.
To resolve this problem, remove the rule, rename all facts to husband_wife/2 and add the definition
married(M,F) :- husband_wife(M,F).
married(F,M) :- husband_wife(M,F).
So the actual deeper problem here was a logical error. In addition to that Prolog's proof mechanism is very simplistic, turning this into a loop. But that is not much more than a welcome excuse to the original logical problem.2
Footnotes:1 This method only works for pure, monotonic fragments. Non-monotonic constructs like not/1 or (\+)/1 must not appear in the fragment.
2 This example is of interest to #larsmans.
The problem is the recursive rules of the predicates affair/2 and married/2. Attempting to use them easily leads to an endless loop (i.e. until the stack memory is exhausted). You must use a different predicate in each case to represent that if X is having an affair with Y, then Y is having an affair with X. You also need to change your definition of the suspect/2 predicate to call those new predicates.
To better understand why you get an endless loop, use the trace facilities of your Prolog system. Try:
?- trace, suspect(Killer, mrBoddy).
and go step by step.

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).

Prolog — symmetrical predicates

I have to simulate family tree in prolog.
And i have problem of symetrical predicates.
Facts:
parent(x,y).
male(x).
female(y).
age(x, number).
Rules:
blood_relation is giving me headache. this is what i have done:
blood_relation(X,Y) :- ancestor(X,Y).
blood_relation(X,Y) :- uncle(X,Y)
; brother(X,Y)
; sister(X,Y)
; (mother(Z,Y),sister(X,Z))
; (father(Z,Y),sister(X,Z))
; (father(Z,Y),brother(X,Z)).
blood_relation(X,Y) :- uncle(X,Z)
, blood_relation(Z,Y).
and I am getting i think satisfactory results(i have double prints - can i fix this), problem is that i want that this relation be symmetrical. It is not now.
blood_relation(johns_father, john):yes
blood_relation(john,johns_father): no
so..is there a way to fix this.
And i need query: All pairs that are not in blood_relation..
Update:
What kinds of relationships is the first statement supposed to satisfy?
blood_relation(X,Y):-blood_relation(X,Y).
sorry..it is a bad copy/paste..it
blood_relation(X,Y):-ancestor(X,Y).
Now fixed above.
here are other rules:
father(X,Y) :-
parent(X,Y),male(X).
mother(X,Y) :-
parent(X,Y),female(X).
brother(X,Y) :-
parent(Z,X),parent(Z,Y),
male(X).
sister(X,Y) :-
parent(Z,X),parent(Z,Y),
female(X).
grandFather(X,Y) :-
parent(Z,Y),parent(X,Z),
male(X).
grandMother(X,Y) :-
parent(Z,Y),
parent(X,Z),female(X).
uncle(X,Y) :-
mother(Z,Y),brother(X,Z).
ancestor(X,Y) :-
ancestor(X,Y).
ancestor(X,Y) :-
parent(X,Z),ancestor(Z,Y).
Mother's brother is in uncle definition. It's kind of strange. I've got rules that I need to implement, and I don't know how I can implement rules besides that. I'm just confused.
Any idea how to make blood_relation symmetric? And not_blood_relation is a new rule. And I need query. This one is really giving me headache. Maybe because relation is written like crap.
And there are no more facts. That's all. All rules, and all facts.
query.. not(blood_relation(X,Y)) doesn't work, and I really don't know why.
For example query:
age(X,Y), Y>18,
not(parent(X,Z)),write(X),nl,fail.
works just fine
The naive solution to making a particular predicate symmetric isn't that far from a decent one. For the sake of generality, let's look at a friendship relation so people don't get tripped up on uncles and the like.
Here are some facts detailing a friendship relation (where, say, the numbers are user ids and the particular ordering of the arguments came from who initiated the friendship).
friends(1,2).
friends(5,2).
friends(7,4).
You'd initially think a rule like "friends(A,B) :- friends(B,A)." would fix things right up, but this leads you to infinite recursion because it tells prolog that if it just swaps the argument one more time it might just work. There is a predicate called "#</2" that tells you whether one term (even a variable) comes before another in the "standard order of terms". The technical meaning isn't all that important here, but what we care about is that for two different terms it is only true for one ordering of them. We can use this to break the infinite recursion!
This single rule will take care of making "friend/2" symmetric.
friends(A,B) :- A #< B, friends(B,A).
As neat as this is, there is an approach way you should take for large projects. Recall that the ordering of the args in my list of facts had some actual meaning (who initiated the friendship). Adding the final rule destroyed future access to this information and, for other people reading the code, hides the symmetric property in a single line of code which is easy to ignore in the face of a block of hard-coded data.
Condsider the industrial-strength solution:
friended(1,2).
friended(5,2).
friended(7,4).
friends(A,B) :- friended(A,B).
friends(A,B) :- friended(B,A).
It is bulkier, but it reads cleanly without using obscure predicates and retains the original information (which you might want again someday in a real application).
--
As for finding pairs that don't have a specific property, make sure you always include some predicate to provide context in your rule when you use negation to look for actual individuals.
potential_enemies(A,B) :- user(A), user(B), \+ friends(A,B).
A bit looks like a homework, isn't it...
One trick which most of beginners of prolog don't think of is list pattern matching. Think of a tree like [a1,[[a2],[b2,[[e3],[f3]]],[c2]]] as in <tree>=[root,[<tree1>,<tree2>,...]]:
%Y is immediate child of X?
child(X,Y,[X|S]) :- member([Y|_],S).
%pick one tree in S and check
child(X,Y,[X|S]) :- member([Z|SS],S),child(Z,Y,[Z|SS]).
%X and Y end up with same root?
sib(X,Y,[R|T]) :- child(R,X,[R|T]), child(R,Y,[R|T]).
I think you can improve upon this like, using pairs as roots, adding genders, giving names to specific relations of members of the tree...
What kinds of relationships is the first statement supposed to satisfy?
blood_relation(X,Y):-blood_relation(X,Y).
That isn't telling you anything that you don't already "know" and is going to cause you recursion headaches. As for the 'no' answer, is looks like you've already gotten all of the answers from the query that you are going to get, and the interpreter is just telling you that there aren't any more.
You really should post more facts, and the definition of uncle/2, and is there a reason why you're not matching a mother's brother, just her sister? You have lots of other issues to work on :-).
For everything that is not a blood relation, try this:
not_blood_relation(X, Y) :- blood_relation(X, Y), !, fail.
not_blood_relation(X, Y).
And ask yourself why it works!

Resources