I'm new to prolog and I'm trying to write a predicate that returns "Yes" if two train stations are on the same line.
line(1,[a,b,c,d,e]);
line(2,[b,g,f,e,i,h]);
line(3,[l,m,g,n,f,o,p,q,i,j]);
same_line(X,Y):-
line(_,L),
member(X,L),
member(Y,L).
Example:
?- same_line(n,j).
Yes
However, I get this error in WIN-PROLOG when compiling: ! Error 67 : Predicate Protected
What am I doing wrong?
Just answering, so that the question goes off the list of unanswered
questions: Yes the (;)/2 is a problem. Further if you really only
want a yes or no, you could also try memberchk/2 instead of member/2.
The code would read:
line(1,[a,b,c,d,e]).
line(2,[b,g,f,e,i,h]).
line(3,[l,m,g,n,f,o,p,q,i,j]).
same_linechk(X,Y):-
line(_,L),
memberchk(X,L),
memberchk(Y,L).
And works as expected:
?- same_linechk(n,j).
true.
The predicate memberchk/2 is part of SWI-Prolog and does not
backtrack after the first time it has found a matching member.
It is essentially a menber/2 with a builtin cut and thus in
the average twice as fast.
Bye
Related
I'm studying for an exam and got stuck on one of the prep questions:
Question:
The following Prolog-program is a meta-program. Explain why this
program is a meta-program and give the output to the three questions
to the program:
?- prove(moving_method(bird,M),N).
?- prove(moving_method(ross,M),N).
?- prove(moving_method(kim,M),N).
I'm trying to run the code(on swish.swi-prolog.org) but it only gives me this error message:
Sandbox restriction!
Could not derive which predicate may be called from
call(C)
prove(A,B)
prove(moving_method(bird,A),B)
The code we are given:
:- dynamic moving_method/2, is_a/2.
is_a(bird,animal).
is_a(ross,albatross).
is_a(kim,kiwi).
is_a(albatross,bird).
moving_method(bird,fly).
moving_method(kiwi,walk).
prove(Fact,l):-
Fact,!.
prove(Fact,X):-
Fact=..[Rel,A1,A2],
is_a(A1,SA),
NewFact=..[Rel,SA,A2],
prove(NewFact,X1),
X is X1 + 1.
The error message might be fairly straight forward but how do I fix it? And why is this a meta-program?
Thank you!
why is this a meta-program?
See: SWI-Prolog Meta-Call Predicates
Meta-call predicates are used to call terms constructed at run time.
In this case passing in the predicate to call, Fact, then running it as a goal.
I have this prolog program.
red(rose).
red(anthurium).
white(rose).
white(gardenia).
white(jasmine).
like(Y,X) :-
red(X),!,
fail
;
white(X).
And below is how it responds to different queries.
?- like(rose,gardenia).
true.
?- like(rose,P).
false.
?- like(Val,anthurium).
false.
?- like(rose,X).
false
The problem I now have is this:
When querying with a variable within the query (Eg: ?- like(rose,X).), Prolog usually responds by returning a value, (something like X=some_val). Why I don't get any value for those variables, but either true or false?
All helpful answers are highly appreciated. Thanks in advance.
Think about what Prolog is doing here:
like(rose,P) succeeds if red(P), so it grabs a possible substitution for P, namely rose or anthurium. Then it traverses the cut and then it fails. But "failing" means that the proof search down that path didn't bring any solution, there are no successful bindings to report (the only fail to get information out of a failing branch is to side-effect to a log file and read check it later). In fact, all bindings will be undone on backtracking. The second branch is white(X), but rose is not white, so we fail here, too.
You can also write:
like(_,X) :- \+ red(X).
like(_,X) :- white(X).
which is a bit more readable. One notices that when calling like(_,X), the goal enclosed by the negation-as-failure operator \+ is nonground. This is bad, and causes a floundering query (in other words, don't do that). I have written this little page on "floundering".
I wrote the following knowledge base in Prolog:
likes(yamini,chocolate).
likes(anuj,apple).
likes(yamini,book).
likes(john,book).
likes(john,france).
Now, when I consult the above file and try the following commands:
| ?- likes(anuj,apple).
(1 ms) yes
| ?- likes(yamini,chocolate).
true ? ;
no
I want to understand when does Prolog replies a 'yes' versus when does it replies 'true'.
That output depends on the toplevel you are using. It seems you are using GProlog. It will output yes when the query succeeds and there are no choice points left (no other possible solutions).
And it will answer true when the query succeeds but there are still other possible solutions to be checked.
This is an artefact of the toplevel (Prolog command line) implementation. Apparently you implementation says true when it could prove a goal and it is unsure whether there may be more solutions. If it is sure that there is only one solution, it says yes.
Here is what SWI-Prolog does:
?- likes(anuj,apple).
true.
Prolog could successfully prove the goal likes(anuj,apple) and it is also sure there are no other ways to prove it otherwise one would see something like this:
?- member(X,[1,2]).
X = 1 ;
X = 2.
where an X that makes the goal true has been found as 1 but there may be other solutions. And indeed there are, namely 2.
Back to our example:
?- likes(yamini,chocolate).
true.
I am examining a Prolog example as a tutorial. In this example I have a predicate with Zero operand like this:
print_all_solutions :-
findall(_,print_solution,_).
how can I call print_all_solution in the console?
When I ask this in the Prolog console I get nothing:
?- print_all_solutions
no answer, also :
?- print_all_solutions.
no answer.
While i get correct answers to other questions like:
?- goal(state([],right,[a,b,c,d],12)).
true.
?- goal(state([],right,[a,b,c,d],19)).
false.
How should I ask a question about predicates with no operand ( /0 ), to see the solution in the console?
I guess your problem is that either init(State) or, more probably, solve(State,Solution,EndState) don't work.
You need to debug: enter these commands after you consulted the source file
?- leash(-all),trace.
?- print_solution.
and you'll get some clue from the Prolog engine
I simply typed this in the console:
findall(_,print_all_solutions,_).
and i get the answer.
I am learning Prolog for an university exam using SWI Prolog and I have some question about this simple program that implement the different predicate that say TRUE if two element are different (if they do not match) and say FALSE if they match.
This is the code:
different(X,X) :- !,
fail.
diferent(_,_).
The problem is that if I try to execute the following query in the Prolog shell I always obtain FALSE:
[debug] 10 ?- different(a,b).
false.
[debug] 11 ?- different(a,a).
false.
As you can see the first query have to say TRUE because a don't match with b
Why?
change diferent(_,_) to different(_,_). Ie it is a spelling error.
Your second predicate is not being examined as it does not match your query.
The program should be
different(X,X) :- !,fail.
different(_,_).
This "exercise" is pointless. Use prolog-dif!
IMO the only reasonable definition of different/2 is:
different(A,B) :- dif(A,B).
If you are using emacs for editing your prolog files (If not I strongly recommend you switching to it) I suggest you using hi-lock-mode. I will highlight in a pattern-like fashion all matches in the file whenever the cursor is over a word. It can save you hours of pain when you develop bigger projects.