Prolog: stop condition? - prolog

Here's a very trivial Prolog knowledge base:
spouse(bill,cheryl).
married(X,Y) :- spouse(X,Y).
married(X,Y) :- spouse(Y,X).
I ran the following queries. Note that sometimes the answer is the correct name (only), but other times the answer is the correct name and "false".
1 ?- married(bill,X).
X = cheryl ;
false.
2 ?- married(cheryl,X).
X = bill.
3 ?- married(X,bill).
X = cheryl.
4 ?- married(X,cheryl).
X = bill ;
false.
Can someone explain this seemingly inconsistent behavior? Thanks in advance.

The false response from Prolog means that Prolog had a choice point to go back to in an attempt to find further answers and it found no more. The order in which your predicates and facts are set up can impact whether it thinks it has more choices to explore.
In the given case:
spouse(bill,cheryl).
married(X,Y) :- spouse(X,Y).
married(X,Y) :- spouse(Y,X).
1 ?- married(bill,X).
X = cheryl ;
false.
2 ?- married(cheryl,X).
X = bill.
3 ?- married(X,bill).
X = cheryl.
4 ?- married(X,cheryl).
X = bill ;
false.
In the two false cases, the query married/2 is satisfied by the first of two married/2 clauses. Once satisified, Prolog realizes it has another choice to make (the second married/2 clause), and prompts for you to look for more. You press ;, then Prolog explores the second (and final) clause, finds no more solutions, and comes back false.
Swap the order of your married/2 clauses and see what happens:
spouse(bill,cheryl).
married(X,Y) :- spouse(Y,X).
married(X,Y) :- spouse(X,Y).
?- married(bill,X).
X = cheryl.
?- married(cheryl,X).
X = bill ;
false.
?- married(X,bill).
X = cheryl ;
false.
?- married(X,cheryl).
X = bill.
As expected, the results are reversed since we've changed which queries are satisfied by the first clause.
The false response can appear inconsistent to beginning Prolog programmers and "feel" like an error or warning, but it's actually a perfectly normal Prolog response. Prolog is quite consistent in its behavior of attempting to find solutions and, when no more choices exist, will return false. If Prolog has exhausted all the other choices before it finds the final solution, it displays the solution and doesn't return false (as in the case above in which the second clause is the only solution).
There is a temptation to try and "clean up" the false responses by using cuts. Although this can have the desired short-term result, it is risky since you are removing choice points from the predicate and as you add data and logic may eliminate solutions which you really want.
Thus, in the modified case:
spouse(bill,cheryl).
spouse(emma,nate).
married(X,Y) :- spouse(X,Y), !. % If we found the spouse, we're done, no more!
married(X,Y) :- spouse(Y,X).
?- married(bill,X).
X = cheryl.
?- married(cheryl,X).
X = bill.
?- married(X,bill).
X = cheryl.
?- married(X, cheryl).
X = bill.
Yay, life is good! But wait, what if we do this:
?- married(X,Y).
X = bill,
Y = cheryl.
?-
Are bill and cheryl the only married couple? No... it left out nate and emma. The cut eliminated the rest of the solutions.

Related

Why does this rule with `not` always return false?

I have this prolog file:
daughter(anna, vera).
daughter(vera, oleg).
daughter(olga, pavel).
daughter(olga, alla).
daughter(alla, lidia).
man(oleg).
man(victor).
man(pavel).
not(P) :- (call(P) -> fail ; true).
woman(X) :- not(man(X)).
?- woman(X). always returns false. ?- man(X). returns all three male entries though.
I also tried woman(X) :- \+man(X). but certain syntax is not the problem it seems.
If I try to check a certain person it works: ?- woman(anna). returns true.
I'm quite new to prolog and can't even suggest what is wrong here.
UPD. I want all people who are not men to be classified as men. The question is - why can't I do woman(X) and get all non-men?
?- woman(anna).
true.
?- woman(X).
false.
?- man(X).
X = oleg ;
X = victor ;
X = pavel.
UPD2. Solution
The problem was caused by floundering as was pointed out in the comments. I needed woman(X) rule to implement this rule: mothers_names(X, Y) :- not(man(X)), daughter(Y,X).
In a nutshell, inverting the query works: mothers_names(X, Y) :- daughter(Y,X), not(man(X)). because first predicate makes X in not(man(X)) limited to several values.

Is it possible to write an inconsistent Prolog program using only pure Prolog, cut and `false`?

This one tickled my interest in theory:
Is it possible to write an inconsistent Prolog program, i.e. a program that answers both false and true depending on how it is queried, using only pure Prolog, the cut, and false?
For example, one could query p(1) and the Prolog Processor would says false. But when one queries p(X) the Prolog Processor would give the set of answers 1, 2, 3.
This can be easily achieved with "computational state examination predicates" like var/1 (really better called fresh/1) + el cut:
p(X) :- nonvar(X),!,member(X,[2,3]).
p(X) :- member(X,[1,2,3]).
Then
?- p(1).
false.
?- p(X).
X = 1 ;
X = 2 ;
X = 3.
"Ouch time" ensues if this is high-assurance software. Naturally, any imperative program has no problem going off the rails like this on every other line.
So. can be done without those "computational state examination predicates"?
P.S.
The above illustrates that all the predicates of Prolog are really carrying a threaded hidden argument of the "computational state":
p(X,StateIn,StateOut).
which can be used to explain the behavour of var/1 and friends. The Prolog program is then "pure" when it only calls predicates that neither consult not modify that State. Well, at least that seems to be a good way to look at what is going on. I think.
Here's a very simple one:
f(X,X) :- !, false.
f(0,1).
Then:
| ?- f(0,1).
yes
| ?- f(X,1).
no
| ?- f(0,Y).
no
So Prolog claims there are no solutions to the queries with variables, although f(0,1) is true and would be a solution to both.
Here is one attempt. The basic idea is that X is a variable iff it can be unified with both a and b. But of course we can't write this as X = a, X = b. So we need a "unifiable" test that succeeds without binding variables like =/2 does.
First, we need to define negation ourselves, since it's impure:
my_not(Goal) :-
call(Goal),
!,
false.
my_not(_Goal).
This is only acceptable if your notion of pure Prolog includes call/1. Let's say that it does :-)
Now we can check for unifiability by using =/2 and the "not not" pattern to preserve success while undoing bindings:
unifiable(X, Y) :-
my_not(my_not(X = Y)).
Now we have the tools to define var/nonvar checks:
my_var(X) :-
unifiable(X, a),
unifiable(X, b).
my_nonvar(X) :-
not(my_var(X)).
Let's check this:
?- my_var(X).
true.
?- my_var(1).
false.
?- my_var(a).
false.
?- my_var(f(X)).
false.
?- my_nonvar(X).
false.
?- my_nonvar(1).
true.
?- my_nonvar(a).
true.
?- my_nonvar(f(X)).
true.
The rest is just your definition:
p(X) :-
my_nonvar(X),
!,
member(X, [2, 3]).
p(X) :-
member(X, [1, 2, 3]).
Which gives:
?- p(X).
X = 1 ;
X = 2 ;
X = 3.
?- p(1).
false.
Edit: The use of call/1 is not essential, and it's interesting to write out the solution without it:
not_unifiable(X, Y) :-
X = Y,
!,
false.
not_unifiable(_X, _Y).
unifiable(X, Y) :-
not_unifiable(X, Y),
!,
false.
unifiable(_X, _Y).
Look at those second clauses of each of these predicates. They are the same! Reading these clauses declaratively, any two terms are not unifiable, but also any two terms are unifiable! Of course you cannot read these clauses declaratively because of the cut. But I find this especially striking as an illustration of how catastrophically impure the cut is.

Prolog - why does the following code generate the solution X=root forever?

black(root).
black(v1).
black(v3).
black(v4).
edge(root,root).
edge(v1,root).
edge(v2,v1).
edge(v3,v1).
edge(v4,v3).
edge(v5,v2).
edge(v5,v4).
edge(v6,v5).
foo(root).
foo(X) :- edge(X,Y), black(Y), foo(Y).
Then I type foo(X) and only get X=root.
I really can't figure out why. We get the first root because of the first part of foo. Then we are supposed to go the the second part, we then proceed to find the edge (root,root). black(root) returns true and so does foo(root) so we get another root solution. Why don't we then go to the edge (v1,root)? What am I missing?
Here is a fragment that is responsible for non-termination called a failure-slice. You need to modify the remaining part somehow in order to avoid that loop.
black(root).
black(v1) :- false.
black(v3) :- false.
black(v4) :- false.
edge(root,root).
edge(v1,root) :- false.
edge(v2,v1) :- false.
edge(v3,v1) :- false.
edge(v4,v3) :- false.
edge(v5,v2) :- false.
edge(v5,v4) :- false.
edge(v6,v5) :- false.
foo(root) :- false.
foo(X) :- edge(X,Y), black(Y), foo(Y), false.
The easiest way to solve this is to reuse closure0/3.
edgeb(X, Y) :-
edge(X, Y),
black(Y).
foo(X) :-
closure0(edgeb, X, root).
... or change your facts. The failure-slice above showed us that the edge(root,root). was part of the problem. What, if we just remove that very fact? Or turn it into
edge(root,root) :- false.
Now foo(X) terminates:
?- foo(X).
X = root
; X = v1
; X = v2
; X = v3
; X = v4
; X = v5
; false.
To avoid hammering ; or SPACE so many times, your carpal tunnels recommend:
?- foo(X), false.
false.
By that we have proven that your program will terminate always. There cannot be any special case lurking around.
Because looking for the 3rd solution starts with retrying foo(Y) when Y=root, and you've already established there are at least 2 distinct ways to prove foo(root). (But, as #WillemVanOnsem points out, it is much worse than that.)

SWI Prolog does not terminate

:- use_module(library(clpfd)).
fact(treated=A) :- A in 0..1.
fact(numYears=B) :- B in 0..sup.
fact(numDrugs=C) :- C in 0..sup.
fact(treated2=D) :- D in 0..1.
fact(cParam=E) :- E in 0..4.
is_differentfact(X,X) :- false.
is_differentfact(Element=_,OtherElement=_) :-
dif(Element,OtherElement).
is_fakt([]).
is_fakt([X|Xs]) :-
fact(X),
maplist(is_differentfact(X),Xs),
is_fakt(Xs).
Why does ?- is_fakt(X) return a list of results answers but after a number of results answers it hangs. I don't know why Prolog cannot return all possible values of X.
You ask:
Why does ?- is_fakt(L) ... but after a number of results answers it hangs.
You say a number. That number is 62 times pressing SPACE to get to that moment of looping. Pretty long isn't it? And your program is tiny. How will you ever get the chance to do the same with a bigger program? Don't worry, there is help. But you need to look at the program from a different angle.
In Prolog understanding the very precise execution of a concrete query is next to impossible. You have two different kinds of control flows interleaved plus strange data structures that do not need to be present, but "come in" later ; sometimes. All that opens up a veritable panoply of possible execution traces that are so full of detail, that your mind will overflow — worse: your mind will still pretend you understand everything but effectively you don't. And the bugs have big party time in your program. Those bugs will bite at some point in time in the future, but only on a bug-to-bite basis. That can be very demoralizing. After all, the program is so small, that should be easy to understand (by the standards of imperative languages). But then, Prolog programs tend to be very compact for problems that are very complex in other languages.
Try to step through with a tracer to see what I mean. You will see all kinds of things happening. And most of them are irrelevant.
Fortunately, there are ways to understand Prolog, but here you have to rely on nice properties of the language itself. For localizing reasons for non-termination, the best is to start to consider a failure-slice. You obtain a failure slice from your program by adding goals false into your program. If the resulting program then still does not terminate, we have a reason why also our original program does not terminate.
Think of it: instead of trying to understand your program we do something humans are much better at: Making an educated guess. That guess can go wrong but we can check that easily. In the beginning you will be pretty awful at guessing. Soon you will see that you can do a lot of things systematically. All code that now becomes irrelevant is stike through.
:- use_module(library(clpfd)).
fact(treated=A) :- A in 0..1.
fact(numYears=B) :- B in 0..sup, false.
fact(numDrugs=C) :- C in 0..sup, false.
fact(treated2=D) :- D in 0..1, false.
fact(cParam=E) :- E in 0..4, false.
is_differentfact(X,X) :- false.
is_differentfact(Element=_,OtherElement=_) :-
dif(Element,OtherElement).
is_fakt([]).
is_fakt([X|Xs]) :-
fact(X),
maplist(is_differentfact(X),Xs),
is_fakt(Xs).
What did we gain? We can narrow down the problem much faster:
?- is_fakt(Xs).
Xs = []
; Xs = [treated=_A], _A in 0..1
; loops.
Before continuing, I try to understand what you mean with is_fakt/1. You probably mean: All the facts by their name, and make sure none is repeated. Now we have only the fact named treated, so we can only produce a list of length 1. And then it loops.
You said:
I don't know why Prolog cannot return all possible values of X.
To be picky, that is not true. Prolog did enumerate all possible values of X. But then it did not terminate.
((Some remarks to consider: Do you really want to get that list in that manner? You will get all permutations! With a list of length n you will get n! different answers. For n = 10 that is 3628800. Is this, what you want? Probably not.))
But let us first stick to identify the precise reason for non-termination.
To better identify the reason, lets "turn off" all answers. So we query is_fakt(L), false instead with:
:- use_module(library(clpfd)).
fact(treated=A) :- A in 0..1.
fact(numYears=B) :- B in 0..sup, false.
fact(numDrugs=C) :- C in 0..sup, false.
fact(treated2=D) :- D in 0..1, false.
fact(cParam=E) :- E in 0..4, false.
is_differentfact(X,X) :- false.
is_differentfact(Element=_,OtherElement=_) :-
dif(Element,OtherElement).
is_fakt([]) :- false.
is_fakt([X|Xs]) :-
fact(X),
maplist(is_differentfact(X),Xs), false,
is_fakt(Xs).
That is a minimal failure-slice. So it is the maplist/2 which does not terminate in the first place. Your idea was to ensure that X has a fact-name that is different to the fact-names in Xs. But if Xs is not bound, that will never terminate. Let's try it:
?- maplist(is_differentfact(X),Xs).
Xs = []
; X = (_A=_B), Xs = [_C=_D], dif(_A,_C)
; X = (_A=_B), Xs = [_C=_D,_E=_F], dif(_A,_C), dif(_A,_E)
; X = (_A=_B), Xs = [_C=_D,_E=_F,_G=_H],
dif(_A,_C), dif(_A,_E), dif(_A,_G)
; X = (_A=_B), Xs = [_C=_D,_E=_F,_G=_H,_I=_J],
dif(_A,_C), dif(_A,_E), dif(_A,_G), dif(_A,_I)
; X = (_A=_B), Xs = [_C=_D,_E=_F,_G=_H,_I=_J,_K=_L],
dif(_A,_C), dif(_A,_E), dif(_A,_G), dif(_A,_I), dif(_A,_K)
; ... .
Not so nice to look at... but we can do it better:
?- maplist(is_differentfact(X),Xs), false.
loops.
So it loops. This is the reason for non-termination. To fix the problem we have to do something in the remaining visible part of the failure slice...
For more, look up other explanations tagged failure-slice
Edited version based on the comments of false.
:- use_module(library(clpfd)).
:- use_module(library(lists)).
fact(treated-X) :- X in 0..1.
fact(numYears-X) :- X in 0..sup.
fact(numDrugs-X) :- X in 0..sup.
fact(treated2-X) :- X in 0..1.
fact(cParam-X) :- X in 0..4.
facts(Facts) :-
findall(X,fact(X),Facts).
is_fact2(_, []).
is_fact2(Facts, [X|Xs]) :-
member(X,Facts),
select(X,Facts,Remaining),
is_fact2(Remaining,Xs).
is_fakt(X) :-
facts(Facts),
is_fact2(Facts,X),
keysort(X,X).
This terminates now.

How do return both a variable result and a true/false in Prolog?

It sounds silly, but lets say my predicate largest/2 returns the largest element in a list...the output should look like this:
?- largest([1,2,3,4,5], X).
X = 5.
false.
I implemented largest, and it works like above except it doesn't output "false". How do I make it so it also outputs this "false." value? This is for an annoying assignment I have to finish. :(
That extra false. or No just means that the person running the program asked to get all possible solutions for X, not just the first possible solution.
On most interactive Prolog interpreters, you check to see if there is another solution by pressing the semicolon (;) key.
sounds like impossible, as if predicate fails, no binding of free variables happens, see
?- A=5.
A = 5.
?- A=5,false.
false.
however
?- A=5;false.
A = 5 ;
false.
To achieve this you should make your predicate "largest" non-deterministic. But to me this seems pretty silly.
If this was part of an assignment, it probably means that your predicate should not yield a second (possibly different) result after backtracking. Backtracking occurs if the user wants the next solution, often by pressing ;. The interpreter often indicates that another solution is possible when it knows there are still paths not fully evaluated.
Suppose you had a predicate foo/1 as follows:
foo(1).
foo(Bar) :-
foo(Baz),
Bar is Baz + 1.
If you ask foo(Bar), the interpreter will respond with Bar = 1. After repeatedly pressing ;, the interpreter will come back with Bar = 2, Bar = 3 and so on.
In your example, finding the largest of a list, should be deterministic. Backtracking should not yield a different answer.
It's up to you to interpret the assignment to mean that you have to allow backtracking but have it fail, or that it would be all right to not even have it backtrack at all.
There is something to the previous answers by #aschepler, #Xonix, and #SQB.
In this answer, we use clpfd for expressing declarative integer arithmetics.
:- use_module(library(clpfd)).
We define largest/2 using the built-in predicate member/2, library meta-predicate maplist/2, and the finite-domain constraint (#>=)/2:
largest(Zs, X) :-
member(X, Zs), % X is a member of the list Zs
maplist(#>=(X), Zs). % all Z in Zs fulfill X #>= Z
Sample queries:
?- largest([1,2,3,4,5], X).
X = 5.
?- largest([1,2,3,4,5,4], X).
X = 5 ;
false.
?- largest([1,2,3,4,5,5], X).
X = 5 ;
X = 5.
?- largest([1,2,3,4,5,5,4], X).
X = 5 ;
X = 5 ;
false.
?- largest([A,B,C,D], X).
A = X, X#>=D, X#>=C, X#>=B ;
B = X, X#>=A, X#>=D, X#>=C ;
C = X, X#>=A, X#>=D, X#>=B ;
D = X, X#>=A, X#>=C, X#>=B.

Resources