minu('-').
minu('+').
minu('/').
f(A):-
atom_chars(A,X),
write(X),
fun(X).
fun([]).
fun([A]):-
not(minu(A)).
fun([Hd|Tail]):-
not(minu(Hd)),
fun(Tail).
I am trying to make an function "f" that takes a string and returns True if "-", "+" or "/" are not in it.
But as soon as I use recursive call. It just returns false.
EDIT ::
SOLUTION FOUND ::
Thank you, lurker... And thank you, Daniel Lyons...
I apologize it has been a long day learning Prolog... I ought to go get some sleep.
f(A):-
atom_chars(A,X),
write(X),
fun(X).
fun([]).
fun([A]):-
not(minu(A)).
fun([Hd|Tail]):-
not(minu(Hd)),
fun(Tail).
I'd try this:
minu('-').
minu('+').
minu('/').
f(A) :-
atom_chars(A, Chars),
\+ (minu(Op), memberchk(Op, Chars)).
By the way, it's important to note that Prolog will not "return" anything; it will either tell you true or false if the goal succeeds or not, so for instance:
?- f("this is a string").
true.
?- f("this i-a string").
false.
?- f("this i+a string").
false.
Related
I don't understand what is the meaning of
[sopio|...], [...|...]|...
in the result of
?- findall([X,Y], indirectowner(X, Y), L).:
L = [[sopio, badri], [temur, badri], [temur, leila], [badri, anuki], [badri, tamar], [tamar, ioseb], [sopio, anuki], [sopio|...], [...|...]|...].
I have dafined following facts:
owner(sopio,badri).
owner(temur,badri).
owner(temur,leila).
owner(badri,anuki).
owner(badri,tamar).
owner(tamar,ioseb).
and clauses:
indirectowner(X,Z) :-
owner(X,Z).
indirectowner(X,Z) :-
owner(X,Y), owner(Y,Z).
The answer is abbreviated in order to avoid having too much output on the screen.
In SWI-Prolog you can press w after the query to write the whole answer but for your query you need YOURquery ; true. because it is deterministic and for the w to be accepted it needs a non-deterministic query.
You can also change the behaviour using Prolog flags.
I have just started learning Prolog, and I'm wondering about the first question of this exercise.
%% Suppose we are working with the following knowledge base:
wizard(ron).
hasWand(harry).
quidditchPlayer(harry).
wizard(X) :- hasBroom(X), hasWand(X).
hasBroom(X) :- quidditchPlayer(X).
How does Prolog respond to the following queries?
wizard(ron). -> true
witch(ron). -> undefined procedure
wizard(hermione). -> false
witch(hermione). -> undefined procedure
wizard(harry). -> true
wizard(Y). -> Y = ron ; Y = harry.
witch(Y). -> undefined procedure
Using swipl on Ubuntu, importing the knowledge base for this exercise, first of course trying to decipher what Prolog will returns, and finally checking by myself.
Ok pretty boring stuff until now, I have seen a few answer to these exercises over Github (here, here and there), and I don't understand the answer to the first one: %% 1. wizard(ron). -> true.
First of all the interpreter is complaining about the two definition of what is a wizard:
Warning: /tmp/prolog/ex15.pl:4:
Clauses of wizard/1 are not together in the source-file
Earlier definition at /tmp/prolog/ex15.pl:1
Current predicate: quidditchPlayer/1
Use :- discontiguous wizard/1. to suppress this message
Secondly, when querying I obtain:
?- wizard(ron).
true ;
false.
The way I get it, first Prolog returns the first fact from the knowledge base, then apply the rule head and find out that ron has neither a broom nor a wand.
All this leading to my question: what subtlety have I missed that makes others writing true as an answer to this query?
what subtlety have I missed that makes others writing true as an answer to this query?
`?- wizard(ron).`
true;
false
You have the clause (fact) wizard(ron). in your KB.
To make the things clearer you can write the fact also as the rule clause:
wizard(ron) :- true.
As you can see this is pretty redundant notation but useful in some cases as the general fact representation.
So your query can be interpreted as follows:
Is there an wizard called ron?
Since you have the fact wizard(ron) :- true.
Prolog will first unify the goal and the head.
In your case unify is trivial comparison because no variables are in the goal and the head.
Then Prolog tries to prove body. The body is builtin predicate true, so you quickly get the answer - true.
Then pressing ';' you initiate the search for the alternative solution.
Since no (more) solutions exist for the query wizard(ron), Prolog writes false.
The dot operator designates the clause end. So you wrongly typed dots in your examples:
-> operator means if-then-else relation. It can be used within clause body.
For example you can write std_member/2 as if_member/2
std_member(X, [ X | _ ]).
std_member(X, [ _ | Xs ]) :-
std_member(X, [ _ | Xs).
if_member(X, [ Y | Xs ]) :-
X = Y -> true;
if_member( X, Xs ).
Given following facts:
route(TubeLine, ListOfStations).
route(green, [a,b,c,d,e,f]).
route(blue, [g,b,c,h,i,j]).
...
I am required to find all the pairs of tube Lines that do not have any stations in common, producing the following:
| ?- disjointed_lines(Ls).
Ls = [(yellow,blue),(yellow,green),(yellow,red),(yellow,silver)] ? ;
no
I came up with the below answer, however it does not only give me incorrect answer, but it also does not apply my X^ condition - i.e. it still prints results per member of Stations lists separately:
disjointed_lines(Ls) :-
route(W, Stations1),
route(Z, Stations2),
setof(
(W,Z),X^
(member(X, Stations1),nonmember(X, Stations2)),
Ls).
This is the output that the definition produces:
| ?- disjointed_lines(L).
L = [(green,green)] ? ;
L = [(green,blue)] ? ;
L = [(green,silver)] ? ;
...
I believe that my logic relating to membership is incorrect, however I cannot figure out what is wrong. Can anyone see where am I failing?
I also read Learn Prolog Now chapter 11 on results gathering as suggested here, however it seems that I am still unable to use the ^ operator correctly. Any help would be appreciated!
UPDATE:
As suggested by user CapelliC, I changed the code into the following:
disjointed_lines(Ls) :-
setof(
(W,Z),(Stations1, Stations2)^
((route(W, Stations1),
route(Z, Stations2),notMembers(Stations1,Stations2))),
Ls).
notMembers([],_).
notMembers([H|T],L):- notMembers(T,L), nonmember(H,L).
The following, however, gives me duplicates of (X,Y) and (Y,X), but the next step will be to remove those in a separate rule. Thank you for the help!
I think you should put route/2 calls inside setof' goal, and express disjointness more clearly, so you can test it separately. About the ^ operator, it requests a variable to be universally quantified in goal scope. Maybe a concise explanation like that found at bagof/3 manual page will help...
disjointed_lines(Ls) :-
setof((W,Z), Stations1^Stations2^(
route(W, Stations1),
route(Z, Stations2),
disjoint(Stations1, Stations2)
), Ls).
disjoint(Stations1, Stations2) :-
... % could be easy as intersection(Stations1, Stations2, [])
% or something more efficient: early fail at first shared 'station'
setof/3 is easier to use if you create an auxiliary predicate that expresses the relationship you are interested in:
disjoint_routes(W, Z) :-
route(W, Stations1),
route(Z, Stations2),
disjoint(Stations1, Stations2).
With this, the definition of disjointed_lines/1 becomes shorter and simpler and no longer needs any ^ operators:
disjointed_lines(Ls) :-
setof((W, Z), disjoint_routes(W, Z), Ls).
The variables you don't want in the result of setof/3 are automatically hidden inside the auxiliary predicate definition.
Is it possible to use retract's returning value?
I just want to make function to print out words, instead of boolean value,
so I try to compare the retract value to print the statement but it seems not working.
The predicate retract/1 can succeed or fail, just like any other predicate.
:- assert(a).
test :-
retract(a),
writeln('a used to be true, but not any more.'), !.
test :-
writeln('a was false').
In the example above, when evaluating test., retract(a) succeeds, so the writeln('...') is evaluated, which always succeeds.
After that, a cut, so we can't backtrack to the second clause.
%:- assert(a).
test :-
retract(a),
writeln('a used to be true, but not any more.'), !.
test :-
writeln('a was false').
In this example, with the assert(a) being commented out, retract(a) fails, so we get to the second clause of test/0, which succeeds by writing "a was false".
I have the following code, where I define is_max as the negation of is_below.
rank(mary,1).
rank(juan,2).
rank(john,3).
rank(jane,4).
is_below(X) :- rank(X,A), rank(Y,B), A<B .
is_max(X) :- not(is_below(X)) .
is_below is true if X is below someone in terms of rank. Therefore the person with the highest/max rank is someone for whom is_below is false (accordingly, is_max is defined).
When I query
is_max(jane) .
This is true (the above is false for mary, juan, and john)
However, when I query
is_max(X) .
This is false. I was expecting it to return jane. My logic seems to be fine, so I am not sure why I don't get jane. Any insight would be really appreciated!
Prolog has negation as failure. Think of it as 'not provable'.
is_max(X) would be true if is_below(X) would always be false. is_below(X) is true for X=mary, so is_below(X) is provable, and is_max(X) is false.
Because of this it's better to use notation \+ instead of not, to remind yourself that it's not true not.
A possible way to fix your code is to explicitly instantiate X:
is_max(X) :- rank(X,_), \+ is_below(X).