I've started learning Prolog recently and came across a problem.
Some people sit around a table. We are given the fact sits_right_of(X, Y) (X sits right of Y). Then I wrote the next rules:
sits_left_of(X, Y) :- sits_right_of(Y, X) (X sits left of Y);
are_neighbors_of(X, Y, Z) :- sits_left_of(X, Z) (X sits left to Z and Y sits right to Z);
next_to_each_other(X, Y) :- are_neighbors_of(_, X, Y); are_neighbors_of(X, _, Y) (X sits next to Y).
How can I find out who is the person who sits two places right (or left) to a given person? Is there some kind of recursive query like sits_right_of(sits_right_of(X, alex))? Do I need to write another rule for finding out who sits n places away from somebody?
You obtain values from a procedure the same way you enter them. Introduce a new variable and try to satisfy sits_right_of(Y, alex). Then, this must also be satisfied: sits_right_of(X, Y). The procedure can be defined like this:
sits_two_places_right_of(X, Y) :- sits_right_of(X, Z), sits_right_of(Z, Y).
Yes, such a procedure can be created analogically to this for every number or persons, or using arithmetics, if you want to make it a parameter.
Related
This program will be tested using SWI Prolog.
Family.pl contains facts about family members, who is married to whom, sorts of things.
Rules must be added at the bottom and submit the modified file.
Write a motherInLaw(X,Y) predicate that means X is Y’s mother-in-law.
Write a grandParent(X,Y) predicate that means X is Y's Grandparent.
Write a grandMother(X,Y) predicate that means X is Y's Grandmother.
Thank you guys!
here are my own answers, could you please take a look and tell me if they are correct? Thanks
motherInLaw(X, Y) : mother(X, Z),couple(Z, Y)
grandParent(X, Y) : parent(X, Z),parent(Z, Y)
grandMother(Z, Y) : mother(X, Z),parent(Z, Y)
You need to write :- instead of : and . at the end of each clause
The grandmother/2 predicate looks very strange. Actually I think the head of the clause should be grandMother(X,Y).
I have been trying to solve a pathfinding problem in Prolog.where the predicates are
edge(a,b).
edge(a,c).
edge(b,d).
edge(c,d).
edge(d,e).
edge(d,f).
edge(f,g).
the rules is
edge(X,Y) :- edge(X,Z), edge(Z,Y).
then when I compiled and run the query
| ?- edge(a,X).
it is showing
Fatal Error: local stack overflow (size: 8192 Kb, environment variable used: LOCALSZ)
then I searched for the solution and found that including atom(x).,atom(y). in our rule can solve the stack overflow problem . i.e the new rule is
edge(X,Y) :- atom(X), atom(Y), edge(X,,Z), edge(Z,Y). and yes it did solved the stack overflow problem .but,I would like to know how exactly this (atom/1)
predicate is solving my problem here?and what does it do to our variables X,Y to solve the StackOverflow problem?
I am a newbie to Prolog any help would be appreciated
thank you. :)
First on naming, the edge/2 name doesn't describe your predicate very well. You probably really want path/2 which consists of one or more edges.
Does atom/1 really solve your problem? In other words, does edge(X, Y) really now provide all of the correct solutions to a query? All that atom/1 does is ensure that its argument is an atom, so it cannot be an unbound variable. So edge(X, Y) does not provide all of the correct solutions. It only yields those solutions that you have direct facts for, since the predicate edge(X, Y) as currently defined always fails with either X or Y unbound.
| ?- edge(a, Y).
Y = b ? ;
Y = c ? ;
no
Where is the solution Y = d for example? edge(X, Y) is only picking up the solutions that are given in your edge/2 facts, but no solutions that include multiple connected edges.
Your original problem is due to infinite recursion, which is a result of edge/2 calling itself unnecessarily. Naming can actually be important here since it makes the logic more precise and correct. We can say that edge(X, Y) means that X and Y form an edge (X and Y are directly connected). We can say that path(X, Y) means there's a path from X to Y via one or more edges. In other words, a path from x to y can either be an edge from x to y, or it can be an edge from x to z and a path from z to y.
path(X, Y) :- edge(X, Y).
path(X, Y) :- edge(X, Z), path(Z, Y).
Now we get:
| ?- path(a, X).
X = b ? a
X = c
X = d
X = e
X = f
X = g
X = d
X = e
X = f
X = g
(1 ms) no
| ?-
There are duplicates since there may be multiple ways of getting from a to e for example. If you included an argument that showed the traversed path, this would become evident.
This solution isn't the end of the story, however. Your current facts are such that there are no "circuitous" paths (paths that eventually revisit the same node if followed). To handle that, you need a predicate argument to keep track of what nodes/edges you've traversed already and avoid traversing them again.
I want to define facts which are true both ways (They all have an arity of 2). I had success with a fact expressing the relationship "opposite" this way:
oppositeDeclare(plus, minus).
opposite(X, Y) :- oppositeDeclare(Y, X).
opposite(X, Y) :- oppositeDeclare(X, Y).
I'm trying to make a simple equation solver, and I would also like to define that if A=B then B=A. I can't just write:
equal(A, B):-equal(B,A).
because I get out of local stack error. However I can't do the same as I did with the "opposite" fact because "equal" needs to work based on the some rules. ("opposite" got it's input from facts only).
Is there a way I can avoid defining all the rules for "equal" twice?
Edit:
I only want to declare simple mathematical facts to see if I can use Prolog to solve other more complicated tasks where I don't know the mechanism for the solution only simple facts.
So far I have used equal/2 to define things like: if A=B+C, then C=A-B. I want to define equal/2 two ways so that I don't have to define if B+C=A, then A-B=C. Ideally after the new rule it could solve an equation for c like this: a=(b+c)/d -> b+c=a/d -> c=(a/d)-b.
The reason I can't use swap is because I have recursive rules for equal/2.
Bear in mind that it will not always work even for simple equations, because not all necessary facts are defined.
Here's the current program with a query:
5 ?- equal(v, X).
X = opr(s, per, t)
% operators: per, times, plus, minus
% equation(LHS, RHS): used to declare physics equations
% equal(LHS, RHS): checks equality in a query
equation(s, opr(v, times, t)). % s=v*t
equation(a, opr(opr(b, plus, c), per, d)). % a=(b+c)/d
oppositeDeclare(plus, minus).
oppositeDeclare(per, times).
opposite(X, Y) :- oppositeDeclare(Y, X).
opposite(X, Y) :- oppositeDeclare(X, Y).
equal(R, opr(A, O, B)) :- equation(R, opr(A, O, B)).
% if there's an equation R=A O B , then R = A O B, where O is an operator (+-*/)
equal(A, opr(R, OY, B)) :- equal(R, opr(A, OX, B)), opposite(OY, OX).
%declaring in one go: if R=A/B then A=R*B, if R=A-B then A=R+B, if R=A+B then A=R-B, if R=A-B then A=R+B
I am not sure I understand you correctly, but aren't you after this simple code?
equal(X, X).
Could you please show some sample input and output that you would like to achieve by using equal/2?
And about opposites, I would write this that way:
oppositeDeclare(plus, minus).
oppositeDeclare(good, evil).
oppositeDeclare(windows, linux).
swap(P, X, Y) :- permutation([X,Y], [X1,Y1]), call(P, X1, Y1).
opposite(X, Y) :- swap(oppositeDeclare, X, Y).
Anytime you would like to use predicate with arity 2 and try swapping arguments, you can use swap/3 in a way presented above.
I am trying to do a small project in prolog where a user can input a list and then it calculates the average, max in the list etc. etc.
So far so good, but I ran into a problem when writing the max function (finds max number in the list). The code is:
maxN([X],X):-!.
maxN([X|L],X) :- maxN(L,M), X > M.
maxN([X|L],M) :- maxN(L,M), M >= X.
The function itself works separately, but I get this error message:
The predicate 'forma::maxN/2 (i,o)', which is declared as 'procedure', is actually 'nondeterm' forma.pro
This is my predicate in the *.cl definition:
maxN: (integer* Z, integer U) procedure (i,o).
I cannot declare it as nondeterm because it causes issues with my whole form. Can you help me/give a hint how to make it a procedure? I am thinking I have to make a cut somewhere but my attempts have failed so far.
P.S. I am using Visual Prolog 7.4.
Edit: After trying the alternatives proposed to make the two rules into one or with an accumulator, I now get that the predicate is 'determ' instead of a procedure. According to my Prolog guide that means that the predicate doesn't have multiple solutions now, but instead has a chance to fail. Basically all code variations I've done up to now lead me to a 'determ'.
The problem is that Prolog sees a choice point between your second and third rules. In other words, you, the human, know that both X > M and M >= X cannot both be true, but Prolog is not able to infer that.
IMO the best thing to do would be to rephrase those two rules with one rule:
maxN([X], X) :- !.
maxN([X|L], Max) :-
maxN(L, M),
X > M -> Max = X
; Max = M.
This way there isn't ever an extra choice point that would need to be pruned with a cut.
Following #CapelliC's advice, you could also reformulate this with an accumulator:
maxN([X|Xs], Max) :- maxN_loop(Xs, X, Max).
maxN_loop([], Max, Max).
maxN_loop([X|Xs], Y, Max) :-
X > Y -> maxN_loop(Xs, X, Max)
; maxN_loop(Xs, Y, Max).
sorry, I don't know the Prolog dialect you're using, my advice is to try to add a cut after the second clause:
maxN([X|L],X) :- maxN(L,M), X > M, !.
Generally, I think a recursive procedure can be made deterministic transforming it to tail recursive. Unfortunately, this requires to add an accumulator:
maxN([],A,A).
maxN([X|L],A,M) :- X > A, !, maxN(L,X,M).
maxN([X|L],A,M) :- maxN(L,A,M).
Of course, top level call should become
maxN([F|L],M) :- maxN(L,F,M).
This Prolog program defines the third argument to be the maximum value of the first two numeric arguments:
max(X, Y, X) :- X >= Y, !.
max(X, Y, Y).
I think that this program works just fine. But I am told that it can give incorrect result. Can you tell when and why?
This is a textbook example.
?- max(5,1,1).
true.
Homework: Why is the program wrong? How do we make the program correct?
EDIT
max(X, Y, X) :- X >= Y, !.
max(X, Y, Y).
Our intention is to say:
If X is greater than Y, then Max is X. Otherwise, Max must be Y.
Instead, what is say is:
When the first and third arguments (X and Max) can be unified, and X is greater than Y, succeed. Otherwise, if the second and third arguments (Y and Max) can be unified, succeed.
The obvious problem arises then the first and third arguments cannot be unified, but the second and the third can.
Instead:
max(X, Y, X) :- X >= Y.
max(X, Y, Y) :- X < Y.
or
max(X, Y, Max) :- X >= Y, !, Max = X.
max(_, Max, Max).
It does work fine, provided the third argument is uninstantiated. The danger here would be if there were a way to backtrack into the second rule, or if the third argument is instantiated to the same value as the second. It's not particularly safe looking because max(X, Y, Y). is equal to max(_, Y, Y) which just sets the result to the second value without any thought. The cut at the end of the first rule effectively ensures that backtracking will not commence if X >= Y, so the second rule should only be entered when X < Y and Z is not already equal to Y.
Though it mostly works, it's not a good habit to get into. People new to Prolog tend to think procedurally and making use of the cut like this to ensure a particular result through procedural trickery ultimately holds you back and leads to convoluted Prolog that cannot be driven in different and interesting ways. There are several other ways of writing this predicate that work just as well but do not rely on the cut to ensure their behavior, for instance:
max(X, Y, X) :- X >= Y.
max(X, Y, Y) :- X < Y.
or
max(X, Y, Z) :- X >= Y -> Z = X ; Z = Y.
Neither of these is vulnerable to the problem of the third being instantiated. Interestingly, this is a great illustration of the difference between a red cut and a green cut. Your code has a red cut, where the behavior is dependent on the cut, but if I simply change my first solution to this:
max(X, Y, X) :- X >= Y, !.
max(X, Y, Y) :- X < Y.
That's a green cut, because the behavior is not dependent on the cut, but Prolog's performance may improve slightly since it won't backtrack into the second clause to try it. Here we're explicitly telling Prolog, don't both making the next check because we know it will fail. With a red cut, there's no other check which will fail.
It's unfortunate that stating the condition twice feels redundant but relying on a single rule feels clunky. In practice, my experience is that scenarios like these are not ultimately all that common; usually you have atoms or structures you can match in the head of the clause that create behavior like we have in my first substitute, but without needing a body. For example:
perform(scan(target, X, Y)) :- ...
perform(scan(calibration, X)) :- ...
This has the same effect: Prolog will backtrack until it unifies successfully, then it will back track again, but the exclusive nature of the matching will prevent another body from being executed. If we find out it's spending too much time backtracking we can add cuts to improve the performance, but in practice it's unlikely to be a problem.