Confusion in output of double negation as failure - prolog

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.

Related

PROLOG, Is it possible to collect all result from a predicate to a list, without using built in predicates, such as bagof or findall

If for example, I have a Prolog predicate like
a(A, B).
Is it possible to collect, given a value of A, is it possible to collect all values of B that succeeds the predicate a, into a list, without using built in predicates such as bagof/3 or findall/3.
You have two obvious options (obvious to me; it seems there is more). One is to indeed use the database to save the state. This has at least one pitfall: depending on the name you decide to use for the temporary state, you might destroy some other state your program is keeping. This is the same old "global state"/"global variable" problem that all languages suffer from.
The other option would be to use a "local variable" and non-backtracking assignment to it to keep the temporary state. This is most probably going to be implementation dependent. For starters, you can look at nb_setarg/3 for SWI-Prolog.
However, both solutions are silly, given that you have findall, bagof, setof. You must motivate the need for something else to replace those. Just saying "is it possible" is not good enough since it is possible, but completely unnecessary, unless you know something else that you aren't telling us.
Here's a sketch of a stupid setof that uses other builtins, though not assert, and not exactly the ones listed by #false in a comment.
We'll use a list accumulator to collect solutions:
stupid_setof(Template, Goal, Set) :-
stupid_setof(Template, Goal, [], Set).
There are two cases to consider: Either the Goal can enumerate a solution we have not seen so far, or the only ones it can enumerate are already in our accumulator.
First, the case where there are no solutions we haven't seen. In this case we're done.
stupid_setof(Template, Goal, SolutionsSeen, Set) :-
\+ ( call(Goal),
\+ member(Template, SolutionsSeen) ),
!,
sort(SolutionsSeen, Set).
Now for the stupid part. Consider:
foo(a).
foo(b).
foo(c).
?- SolutionsSeen = [], foo(X), \+ member(X, SolutionsSeen), !.
SolutionsSeen = [],
X = a.
?- SolutionsSeen = [a], foo(X), \+ member(X, SolutionsSeen), !.
SolutionsSeen = [a],
X = b.
?- SolutionsSeen = [a, b], foo(X), \+ member(X, SolutionsSeen), !.
SolutionsSeen = [a, b],
X = c.
?- SolutionsSeen = [a, b, c], foo(X), \+ member(X, SolutionsSeen), !.
false.
So given a list of solutions we've seen before, we can force Goal to backtrack until it gives us one that we haven't seen before. Note that these queries are independent: In each one we have a completely fresh copy of the foo(X) goal that starts enumerating from a.
We can do the same thing programmatically by copying the original goal before calling it, forcing it to start a fresh enumeration from a fresh instance of the Goal. If this finds a new solution, we can add it to our solutions, then repeat with another fresh copy of the goal, forcing it to enumerate yet another new solution, and so on:
stupid_setof(Template, Goal, SolutionsSeen, Set) :-
copy_term(Goal-Template, GoalInstance-Solution),
call(GoalInstance),
\+ member(Solution, SolutionsSeen),
!,
stupid_setof(Template, Goal, [Solution | SolutionsSeen], Set).
If Goal has N answers, this will enumerate on the order of N**2 of them and do corresponding linear searches in the solutions list. It will also perform any side effects that Goal has multiple times.
But it "works":
?- stupid_setof(X, foo(X), Xs).
Xs = [a, b, c].
And, despite all of its stupidity, this is still less stupid than the standard setof/3 if Goal has no solutions:
:- dynamic bar/1. % no clauses
?- setof(X, bar(X), Set).
false.
?- stupid_setof(X, bar(X), Set).
Set = [].

How to print all females in prolog if my facts only contains male property

Lets suppose my db.pl file consists of only
male(Oliver)
male(james)
male(sam)
female(X) :- \+ male(X)
Now if I query,
?- male(X).
Then this will successfully return all the males.
But if I query,
?- female(X)
Then this will not. However, if I put a name in the female predicate, it correctly gives the output as yes/no.
What am I missing here? How do I get the list of all females? Or basically list of "not male".
I thought I'd give a proper answer as well. As mentioned in the comments, the fact male(Oliver). contains the variable Oliver such that e.g. also male(catherine_the_great) succeeds. But fixing this mistake will not solve the problem. Suppose we fix the facts for male and define female as above:
male(oliver)
male(james)
male(sam)
female(X) :-
\+ male(X).
Then we can not derive male(catherine_the_great) anymore but female(catherine_the_great) succeeds:
?- male(catherine_the_great).
false.
?- female(catherine_the_great).
true.
Unfortunately, by this definition, a hamburger is also female:
?- female(hamburger).
true.
What's even worse is, when we ask if there exists someone female (at all!), we get no as an answer:
?- female(X).
false.
The reason for this is that \+ is not classical negation(*) but what is called weak negation / negation as failure. \+ male(X) is true if there is no X such that male(X) is derivable. But as soon as male/1 succeeds with any solution (e.g. male(oliver)), the negation fails. In such cases the substitution male(X) is not proper substiution for female(X) but how are we supposed to get a list of all women? A possible solution is a list of persons of which we define male/female as subsets:
person(oliver).
person(james).
person(sam).
person(jackie).
person(selma).
male(oliver).
male(james).
male(sam).
female(X) :-
person(X),
\+ male(X).
When we query a list of all women, we now get:
?- female(X).
X = jackie ;
X = selma.
I'd rather use a separate predicate listing women though because it is less error prone when adding new persons.
In general, negation as failure is rarely safe. Two rules of thumb i have for myself:
whenever \+ p(X) appears as a goal, it is fully instantiated (a ground term). In our case, this is what person assures.
p(X) terminates for every ground term X. This assures termination of the negation as well.
(*) in classical logic, the rule of generalization female(jackie) → ∃X female(X) holds but here we can not derive ∃X female(X) despite being able to derive female(jackie).

Why do I get a Infinite Loop (Prolog)

I am just starting to learn Prolog and I played around with it. Now I got to a point where I´m stuck. The program i wrote gets into an infinite loop when I ask for
?- q(b).
and I don´t understand why it does that. It would be nice if someone could explain it to me.
p(a).
p(b).
q(Y) :- r(X), r(Y).
r(X) :- r(f(X)).
r(a) :- p(c).
r(a) :- p(a).
r(b) :- p(b).
As said in the comment, the loop is caused by r/1. To show why, yust type ?- trace, q(b). Look at the trace (ignore by now the singleton warning):
Call:q(b)
Call:r(_4244)
Call:r(f(_4162))
Call:r(f(f(_4162)))
Call:r(f(f(f(_4162))))
Call:r(f(f(f(f(_4162)))))
Call:r(f(f(f(f(f(_4162))))))
Call:r(f(f(f(f(f(f(_4162)))))))
Call:r(f(f(f(f(f(f(f(_4162))))))))
Now you can see that it try to derives r/1 entering a loop. You can see also this question to have a more in depth explaination.
Notice that in prolog, the order of the clauses matters. Just try to put the line r(X) :- r(f(X)). to the bottom of your program. Now try ?- q(b). On the first answer you get true because prolog unifies X with a and Y with b before entering in a loop.
Another way to identify reasons for non-termination is to reduce the number of inferences your program will execute by adding goals false into your program:
q(Y) :- r(X), false, r(Y).
r(X) :- r(f(X)), false.
r(a) :- false, p(c).
r(a) :- false, p(a).
r(b) :- false, p(b).
?- q(Y).
loops.
Since this program is still looping, you will need to modify something in the visible part. Note how many things have been removed entirely! No matter how p/1 is defined, this problem will persist.
If you look at q/1 closely, you see one of the problems:
q(Y) :- r(X), false, r(Y).
The variable Y is not used in the visible part at all. The X appears just once. Thus, r(X) will be the most general query possible and thus it will have the worst termination property possible (that depends on the definition of r/1, indeed). In any case, the argument of q/1 has no influence on termination!
There is another property to conclude: The order of clauses does not have any influence on the termination property! You can see this easily: No matter where the clauses that have been removed entirely with false appear, they can be removed.
For more, see failure-slice.

What does Prolog assert/1 do with the term it is passed?

I'm trying to understand what assert and retract do with the term they are passed. If I run the following:
?- assertz(item(first)).
true.
?- assertz(item(second)).
true.
?- assertz((item(Y) :- =(Y, third), writeln(Y))).
true.
?- retract(item(X)).
X = first ;
X = second ;
false.
retract/1 removes all of the items but my writeln/1 is never called, so it appears retract is not actually resolving the term it is passed. It looks like it is doing some special operation where it:
Unifies the term with only facts (i.e. rules with no tail) in the database
Retracts each one after applying the substitution from unification
Is this right? Or is something else happening here?
Said another way: If I write my own single argument rule, Prolog does not automatically unify item(X) with the database and iterate through all facts that are item/1. It just gives me item(X). How is retract doing its magic?
?- assertz((myRule(X) :- writeln(X))).
true.
? myRule(item(X)).
item(_2556)
true.
Answer with further clarification:
Based on the answer by User9213, it appears that the answer is "retract (but not assert!) has a funny behavior where it does a simple unification of its term before it does something to the database". I'm left wondering why other built-in functions that I've seen (like atom/1 and writeln/1) don't appear to do this. Maybe it is more common than I've experienced?
For consistency, it seems like retract should have required ground terms and if the user wanted to do something like my above example, they could have done this:
?- (item(X), retract(item(X))).
It all makes me think I'm missing something or maybe these built in functions were just inconsistently designed? Any clarification that would explain that would be great.
To add my voice to the chorus, yes, all these predicates (assert*, retract*) manipulate the Prolog database of facts and rules; they do not evaluate their arguments as if they were facts or rules. Yes, they just do "syntactic" unification between their argument and the facts and rules in the database.
Prolog is a homoiconic language. The program can be manipulated as if it was data; the data structures can be interpreted as if they were the program. Most importantly: whether a certain structure is data or program depends only on the context.
You seem to understand this, but for the next poor soul that stumbles across your question and this answer, here is a toy example to demonstrate.
There is a built-in predicate atom/1 that succeeds if its argument is, well, an atom:
?- atom(foo).
true.
?- atom(Bar). % Bar is a free variable, which is not an atom
false.
?- atom(atom(bar)). % atom(bar) is a compound term, which is not an atom
false.
But atom(bar) is just a compound term in the last query. It is a compound term with a functor atom/1. Its only argument is an atom. So if you now queried it:
?- atom(bar).
true.
There is also this really nice predicate called call. It makes it even easier to blur the lines between program and data. The following three queries are identical in meaning:
?- atom(bar).
true.
?- call(atom, bar).
true.
?- call(atom(bar)).
true.
In addition, you can dynamically (at run-time) create a data structure and evaluate it as program. Here is a naive implementation of call/2 that can evaluate predicates, provided a predicate name and a list of arguments. It constructs the compound term using "univ" and evaluates it by just placing it in a slot where a subgoal is supposed to be. I'll call it my_call/2 and I will add it to the database using assertz:
?- assertz((my_call(Name, Args) :- Goal =.. [Name|Args], Goal)).
true.
?- my_call(between, [1, 3, X]).
X = 1 ;
X = 2 ;
X = 3.
Do you see what is going on? (Note: it seems that call is a relatively new addition to Prolog. Before call was widely available, you had to do this trick if you wanted to meta-call predicates. I don't know this from experience, just educated guessing based on things I've read or heard and can't be bothered to cite right now.)
So, let's try that again. In reality things are more complicated, but very simplified:
A Prolog program is a set of predicates. Not ordered!
Each predicate is a list of clauses. It is a list because a predicate may have 0 or more clauses, and they have order.
A clause can be a fact or a rule.
A rule is a compound term with functor :-/2. Yes, this is right. To see what I mean:
?- assertz(:-(foo(X), between(1, 3, X))).
true.
?- listing(foo/1).
:- dynamic foo/1.
foo(A) :-
between(1, 3, A).
true.
This is just another way to write it. It is more conventional.
So indeed, these two are very different:
foo(X). % a fact
foo(X) :- between(1, 3, X). % a rule
You cannot unify the one with the other. This is why, if you want to retract foo(X) :- between(1, 3, X), you cannot just pass foo(X) as the argument to retract. Or, to complete your example:
?- assertz(item(first)).
true.
?- assertz(item(second)).
true.
?- assertz((item(Y) :- =(Y, third), writeln(Y))).
true.
?- retract(item(X)).
X = first ;
X = second ;
false.
?- retract((item(X) :- X = Y, writeln(X))).
Y = third.
Do you see it now?
I had a vague memory of there being a retractall/1 that lives alongside retract/1 and it turns out the reason for it is situations like this. retract/1 accepts a Prolog term, as the documentation states:
retract(+Term)
When Term is an atom or a term it is unified with the first unifying fact or clause in the database. The fact or clause is removed from the database.
Emphasis added by me.
This is illustrated by the following:
?- asserta(foo(X) :- X = 2 ; X = 4).
true.
?- foo(X).
X = 2 ;
X = 4.
?- retract(foo(X)).
false.
?- foo(X).
X = 2 ;
X = 4.
?- retract(foo(X) :- X = 2 ; X = 4).
true.
?- foo(X).
false.
Note that if you furnish the complete clause you gave to asserta/1, it will be retracted. As #CapelliC points out below, you can also furnish a clause with a variable as a parameter to retract things with bodies:
retract(foo(X) :- Y).
However, if you do want to retract things that match a pattern, you can use retractall/1, which the documentation states:
retractall(+Head)
All facts or clauses in the database for which the head unifies with Head are removed.
This is illustrated by the following:
?- asserta(foo(X) :- X = 2 ; X = 4).
true.
?- foo(X).
X = 2 ;
X = 4.
?- retractall(foo(X)).
true.
?- foo(X).
false.
Another important difference between these two is that retract/1 will remove one thing at a time, and it will unify those things:
?- asserta(foo(X) :- X = 2).
true.
?- asserta(foo(X) :- X = 4).
true.
?- retract(foo(X) :- Y).
Y = (X=4) ;
Y = (X=2) .
This is in contrast to retractall/1 which will remove everything that matches the pattern, without unifying anything:
?- asserta(foo(X) :- X=2).
true.
?- asserta(foo(X) :- X=4).
true.
?- foo(X).
X = 4 ;
X = 2.
?- retractall(foo(X)).
true.
?- foo(X).
false.
So, retract/1 is really for doing one-at-a-time retractions but expects something shaped like the term you asserted, whereas retractall/1 only wants a head, treats it as a pattern, and will remove as many things as match the pattern.
This certainly helped me improve my understanding of Prolog, so I hope it helps you as well!
The definition of assert in swi-prolog is:
Assert a clause (fact or rule) into the database. The predicate asserta/1 asserts the clause as first clause of the predicate while assertz/1 assert the clause as last clause. The deprecated assert/1 is equivalent to assertz/1. If the program space for the target module is limited (see set_module/1), asserta/1 can raise a resource_error(program_space) exception. The example below adds two facts and a rule. Note the double parentheses around the rule.
Hence, it does not call or infer anything! It's just an assertion for the fact and the rule into the active memory.

Prolog: Error out of global stack with what looks like ONE level of recursion to me

I am quite rusty in prolog, but I am not sure why things like this fail:
frack(3).
frack(X) :- frack(X-1).
So, if I evaluate frack(4). from the interactive prompt with the above facts defined, I expect that it should not have to endlessly recurse, since 4-1 = 3. But I get this error in SWI-Prolog:
ERROR: Out of global stack
Try it:
?- 4-1 = 3.
false.
Why? Because 4-1 = -(4, 1), which clearly is not a number but a compound term.
To reason about integers in Prolog, use clpfd constraints, for example (using GNU Prolog or B-Prolog):
| ?- 4-1 #= X.
X = 3
In SWI-Prolog, the graphical tracer may be useful for you to see what happens:
?- gtrace, frack(4).
For more complex debugging, I recommend failure-slice as shown in false's answer.
Here is the reason for this non-termination. Your query does not terminate, because there is a failure-slice of your program that does not terminate:
?- frack(4).
frack(3) :- false.
frack(X) :-
frack(X-1), false.
You can fix this only by modifying something in the visible part. Three SO-answers suggest to use (is)/2. But this will not remove non-termination! In fact, using (is)/2 leads to essentially the same fragment:
?- frack(4).
frack(3) :- false.
frack(X) :-
Y is X - 1,
frack(Y), false.
At least, frack(4) now succeeds, but it will loop on backtracking. You have to change something in the visible part, like some test for X, in order to avoid non-termination. See failure-slice for more.
frack(X) :- frack(X-1).
should be
frack(X) :- Y is X - 1, frack(Y).
The way you wrote it, X-1 expression of the first level unifies with X variable at the next level, never going for the frack(3) fact.
Prolog doesn't do arithmetic unless you use the is operator:
frack(X) :- X1 is X-1, frack(X1).

Resources