Binary logic in prolog - 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.

Related

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 Predicates Exam Questions

I'm studying for an Artificial Intelligence exam and struggling to understand how to answer certain questions focusing on Predicates. The two questions in particular are:
Define a predicate which behaves as follows -
?- stage_name(billie, Name).
Name = rose
yes
?- stage_name(jenna,Name).
Name = clara
yes
Write a predicate that takes two argument and is true if both actors are on the same show. Thus
?-same_show(david,clara).
is true, whilst
?-same_continent(elisabeth,skippy).
is not
I don't really understand how I would answer these questions, and I'm finding very little Prolog information online. I would appreciate some help. Apologies for the formatting.
1:
stage_name(billie,rose).
stage_name(jenna,Name) :- Name=clara.
Explanation:
Given a query, Prolog looks for an appropriate predicate according to the input parameters and the name and "executes" it. The result is either true/false if no output parameter is given. In this case there is one (Name) which can be seen from the leading capital letter. Note that there are two possible ways to implement this. The former is probably the most common (predicates of this form are called "facts" whereas predicates such as the lower are called "rules").
2:
As mentioned in my comment, I don't really understand the connection between the two given predicates. Also it feels like there is something missing such as a facts that determine which person is on which show...
Assuming such facts are missing, I would write the Prolog program as follows:
onShow(david, s1).
onShow(clara, s1).
onShow(bernie, s2).
same_show(P1, P2) :- onShow(P1,X), onShow(P2,X).
Explanation:
The predicate is only true if both P1 and P2 visit the same show X.
Hints:
A "comma" represents a logical AND operator. Having different rules with the same name and parameter count represents logical OR. Edit: As Boris mentioned in a comment, this is not exactly true. This association simply helped me to understand the connection between "Logical Predicates" and "Prolog Predicates".
Visit SWISH to test your Prolog programs.

Prolog: "if then else", using cut

This is an easy question: I've seen this example in a Prolog text book.
It is implementing if-then-else using a cut.
if_then_else(P, Q, R) :- P, !, Q.
if_then_else(P, Q, R) :- R.
Can anyone explain what this program is doing, and why it is useful?
The most important thing to note about this program that it is definitely not a nice relation.
For example, from a pure logic program, we expect to be able to derive whether the condition had held if we pass it the outcome. This is of course in contrast to procedural programming, where you first check a condition and everything else depends on the condition.
Also other properties are violated. For example, what happens if the condition actually backtracks? Suppose I want to see conclusions for each solution of the condition, not just the first one. Your code cuts away these additional solutions.
I would also like to use the relation in other cases, for example, suppose I want to detect superfluous if-then-else constructs in my code. These are solutions to queries similar to:
?- if_then_else(NoMatter, Same, Same).
If if_then_else/3 were a pure relation, we could use it to answer such queries. As it is currently implemented, it yields incorrect results for such queries.
See logical-purity and if_/3 for more information.

Recursive reference in prolog

I meet some problem when I try to implement
friends(mia, ellen).
friends(mia, lucy).
friends(X,Y) :-
friends(X,Z),
friends(Y,Z).
and when i ask ?- friends(mia, X)., it run out of local stack.
Then I add
friends(ellen, mia) friends(lucy, mia)
I ask ?- friends(mia, X). ,it keeps replying X = mia.
I can't understand, why it is recursive?
First, two assumptions:
the actual code you wanted to write is the following one, with appropriate dots:
friends(mia,ellen).
friends(mia,lucy).
friends(X,Y) :-
friends(X,Z),
friends(Z,Y).
transivity holds: friends of friends are my friends too (I would rather model friendship as a distance: "A is near B" and "B is near C" does not necessarly imply "A is near C"). repeat's answer is right about figuring out first what you want to model.
Now, let's see why we go into infinite recursion.
Step-by-step
So, what happens when we ask: friends(mia,X) ?
First clause gives Y=ellen (you ask for more solutions)
Second clause gives Y=lucy (you ask again for more solutions)
Stack overflow !
Let's detail the third clause:
I want to know if friends(mia,Y) holds for some variable Y.
Is there a variable Z such that friends(mia,Z) holds ?
Notice that apart from a renaming from Y to Z, we are asking the same question as step 1 above? This smells like infinite recursion, but let's see...
We try the first two clauses of friends, but then we fail because there is no friends(ellen,Y) nor friends(lucy,Y), so...
We call the third clause in order to find if there is a transitive friendship, and we are back to step 1 without having progressed any further => infinite recursion.
This problem is analogous to infinite Left recursion in context-free grammars.
A fix
Have two predicates:
known_friends/2, which gives direct relationships.
friends/2, which also encodes transitivity
known_friends(mia,ellen).
known_friends(mia,lucy).
friends(X,Y) :- known_friends(X,Y).
friends(X,Y) :- known_friends(X,Z), friends(Z,Y).
Now, when we ask friends(mia,X), friends/2 gives the same answer as the two clauses of known_friends/2, but does not find any answer for the transitive clause: the difference here is that known_friends will make a little progress, namely find a known friend of mia (without recursion), and try to find (recursively) if that friend is a friend of some other people.
Friends' friends
If we add known_friends(ellen, bishop) :-) then friends will also find Y=bishop, because:
known_friends(mia,ellen) holds, and
friends(ellen,bishop) is found recursively.
Circularity
If you add cyclic dependencies in the friendship graph (in known_friends), then you will have an infinite traversal of this graph with friends. Before you can fix that, you have to consider the following questions:
Does friends(X,Y) <=> friends(Y,X) hold for all (X,Y) ?
What about friends(X,X), for all X ?
Then, you should keep a set of all seen people when evaluating friends in order to detect when you are looping through known_friends, while taking into account the above properties. This should not be too difficult too implement, if you want to try.
This clause of friends/2 is flawed:
friends(X,Y) :- friends(X,Z),friends(Y,Z).
Translate that into English: "If X and Y have a mutual friend Z, then X and Y are friends."
Or, let's specialize, let X be "me", let Y be my neighbour "FooBert", and let Z be "you": So if I am your friend and FooBert is your friend... does that make me and FooBert friends? I don't think so, I hate that guy---he always slams the door when he gets home. :)
I suggest you consider the algebraic properties that the relation friends/2 should have, the ones it may have, and ones it should not have. What about reflexivity, symmetry, anti-symmetry, transitivity?

How to represent uniqueness?

I am trying to write an agent for determining what card a player has, and I am struggling to represent that each card can only have been dealt to a single player.
So have I have something^ like this:
player(p1).
player(p2).
card(ace).
card(king).
card(queen).
card(jack).
but I am struggling on writing the rule for uniqueness. Borrowing something from logic class, I though about defining uniqueness as "if X has Y, then if something has Y, that something must be X".
has_card(P, C) :-
player(P),
card(C),
not(player(P2),
P2 =\= P,
has_card(P2, C)
).
but this fails because not/3 is not defined.
I tried rewriting it as:
has_card(P, C) :-
player(P),
card(C),
player(P2),
P2 =\= P,
not(has_card(P2,C)).
but then the query (which I expect to return false)
has_card(P, ace).
errors out with
ERROR: =\=/2: Arithmetic: `player1/0' is not a function
So, how can I represent uniqueness?
^ complicating --likely-- unnecessary details omitted
EDIT: in first attempt at has_card I have P2==P which should have been P2=\=P, fixed now
First off, as the error is telling you, you are using =\=, which is arithmetic inequality. For comparing on standard order of terms, you should use \==.
Then, the "not" as in "true when negated goal not true", you should probably use \+, like this:
\+ a == b
which is the same as
a \== b
The not/1 predicate is still available in most Prolog implementations but not recommended.
Fixing these two things will sort out the problem you are having at the moment.
But, as it is at the moment, your has_card/2 at no point maps a card to a player, really (it uses circular logic as far as I can see). Since you are not showing how exactly you know which cards belong to which player at any given moment, it is difficult to comment on that. Either way, some sort of term that you pass around would be probably better than changing the database with assert and retract.

Resources