I'm new to PROLOG and am at the very beginning of the exercises on this page. Given the rules parent(X, Y) and male(X), I'm trying to define a rule mother(X, Y) as
mother(X, Y) :-
not(male(X)),
parent(X, Y).
However, in GNU Prolog I get the following error:
| ?- mother(lina, julia).
uncaught exception: error(existence_error(procedure,not/1),mother/2)
| ?-
\+/1 is the ISO Prolog predicate to "negate". Note that "negate" means here not provable at that point.
You can refer to this excellent answer by #false for more on the subject
The solution is actually in the exercise file on that page:
female(X) :- \+ male(X).
As #Mog said, negation is the unary \+ operator.
Related
I am trying to learn prolog and i came across the following problem:
Given -
try(X):-not(not((member(X,[a,b,c])))),write(X).
I would expect the query ?- try(X)., for the following query to be something like
X=a
a;
X=b
b;
X=c
c.
But in fact, the output is:
?- try(X).
_12010
true.
Why is that? Why the variable is not initiated to some value?
In addition to what #VictoriaRuiz says, notice a few other things:
?- \+ member(X, [a,b,c]).
false.
This is false because member(X, [a,b,c]) has solutions, but the variable binding is lost when you negate it. So that means
?- \+ \+ member(X, [a,b,c]).
true.
is the same as
?- \+ false.
true.
In other words, there's nowhere for X to materialize from. Your write(X) happens outside the scope of the variable binding for X, it's as though you did this:
?- \+ false, write(X).
_4082
true.
which is basically the same as
?- write(X).
_4014
true.
If you wanted to see evidence of backtracking in the negation, you might expect to see it with this query:
?- \+ \+ (member(X, [a,b,c]), write(X), nl).
a
true.
But because you obtained a true solution on the first try, the negation of that is false. Then the negation of that is true. So we see that it produced a solution inside the goal (member(X, [a,b,c]), write(X), nl), which is enough to know that the negation of that is false. Negating false again gives you true, but no variable bindings.
Prolog operates with a closed world assumption. You provide a knowledge base and only what is in it is true.
When you negate, Prolog doesn't know what values to check for. It can't add "a" as a part of this universe that is worth checking. And since it can't check for anything, it just returns nonsense.
I am trying to port this Prolog code to Datalog in Racket, using example at bottom of this page.
#lang datalog
edge(a, b). edge(b, c). edge(c, d). edge(d, a).
path(X, Y) :- edge(X, Y).
path(X, Y) :- edge(X, Z), path(Z, Y).
path(X, Y)?
pathall(X,X,[]).
pathall(X,Y,[X,Z|L]):- arc(X,Z),pathall(Z,Y,L).
pathall(a, d)?
But it is giving this error at [X,Z|L] on last line of code:
read: expected a `]' to close `['
How do I represent a list in Datalog? Thanks for your help.
Datalog is a syntactic subset of Prolog.
In particular, compound terms such as lists are not supported in Datalog.
I'm wondering how would I be able to call a nephew or niece in a family tree without using a sibling fact for prolog. I can't figure out a way to do it by calling the uncle directly.
For example:
parent(elli, lisa).
parent(kelly, lisa).
parent(ben, claire).
parent(lisa, claire).
grandparent(X, Y) :- parent(X, Z), parent(Z, Y).
Since ellie or kelly is ben's niece, I have the rule that when called by grandparent(X, claire). will give elli and kelly as the grandchild of claire. How would I make a rule to be able to call niece(ben, X). so it'll list all of ben's niece. I can't figure out a way to do it with only the parent fact, the only way of doing it would be to include a sibling fact but is there a way to do it without making a sibling fact?
I'm very new to prolog, literally like a week ago so please excuse me if I don't understand it that well.
brother(X, Y) :- male(X), parent(X, Z), parent(Y, Z), X \= Y.
uncle(X, Y) :- brother(X, Z), parent(Y, Z).
I'm just learning Prolog, and I'm reviewing lecture notes and all the notes say is that:
given the following definition for directed graphs:
path(X, Y) :- edge(X, Y).
path(X, Y) :- edge(X, Z), path(Z, Y).
If we wanted to make this an undirected graph, defining
edge(X, Y) :- edge(Y, X). alone doesn't work, and I can't figure out why.
X to Y has an edge if Y to X has an edge. Seems to make sense to me.
The notes don't really clarify why not, but it does define that the proper solution would be:
edge1(X, Y) :- edge(X, Y).
edge1(X, Y) :- edge(Y, X).
to what we already had.
Can anyone explain this to me, please and thanks? <3
There are several potential sources of non-termination in your program.
First, with the rule edge(X, Y) :- edge(Y, X). your program will never terminate. Regardless of where you add this rule to your program.
What is often quite irritating is that your program will still produce many answers which somewhat suggests that it works. However, it will never stop.
The best way to understand this, is to consider a slightly modified program, called a failure-slice. This modified program will share many properties with your program. Not all of them, but some. We will add goals false into your program. If the resulting program loops, the original program will loop as well.
path(X, Y) :- edge(X, Y), false.
path(X, Y) :- false, edge(X, Z), path(Z, Y).
edge(a, b) :- false.
edge(X, Y) :- edge(Y, X).
Second, there is another source of non-termination in your improved program. Here is the related failure-slice:
path(X, Y) :- false, edge1(X, Y).
path(X, Y) :- edge1(X, Z), path(Z, Y), false.
edge1(X, Y) :- edge(X, Y).
edge1(X, Y) :- edge(Y, X).
edge(a, b).
edge1/2 now always contains cycles, so this fragment will loop for path(a, Y). and more generally also path(X, Y), false.
To solve this problem, you will have to rewrite path/2.
You can rewrite this in a generic manner by using closure0/3 and path/4!
So path/2 can be defined as:
path(X, Y) :-
closure(edge, X, Y).
Because rules don't work the same as facts, and you are spiraling off into an infinite loop if you use the same predicate.
Let's take the example ?-edge(5,2). We will end up calling --
edge(5,2) :- edge(2,5).
Ok, what happens when we call edge(2,5)?
edge(2,5) :- edge(5,2).
... Uh oh. Logic circle.
When using edge1, you are simply creating a wrapper for your predicate to escape the recursive definition.
I am learning Prolog and would just like to check myself:
I think this question is very basic but I am just beginning.
father(X,Y)
mother(X,Y)
male(X)
female(X)
parent(X,Y)
diff(X,Y)
To write a clause for is_mother(X) is this correct?
is_mother(X):- female(X), parent(X,Y).
Thank you
is_mother(X) :- female(X), parent(X,Y).
This is technically correct in that it says, X is a mother if X is female, and X is the parent of someone (Y). In this definition, Prolog will give you a warning about Y being a "singleton" variable since you don't use its value. To avoid that warning, you can use _ or a name that starts with _ to indicate a variable whose value you don't care about and Prolog won't warn that you're not using:
is_mother(X) :- female(X), parent(X,_).
The terms female(X) and parent(X,_) assume that you have either predicates female(X) and parent(X,Y) or you have facts, such as (for example) female(sally). where sally is an "atom" (a constant in Prolog), and/or parent(sally, tom).