0

I've started learning PROLOG and I have a problem with a very basic example. I'm using SWI PROLOG and the code is as follows:

is_true(a).
is_true(c).
is_true(d).
is_false(b).
is_false(e).

and(A,B) :- is_true(A),is_true(B).
nand(A,B) :- \+(and(A,B)).

Then:

[imanol@I56106 prolog]$ swipl
Welcome to SWI-Prolog (Multi-threaded, 64 bits, Version 6.6.4)
Copyright (c) 1990-2013 University of Amsterdam, VU Amsterdam
SWI-Prolog comes with ABSOLUTELY NO WARRANTY. This is free software,
and you are welcome to redistribute it under certain conditions.
Please visit http://www.swi-prolog.org for details.

For help, use ?- help(Topic). or ?- apropos(Word).

?- consult(test).
% test compiled 0.00 sec, 8 clauses
true.

?- and(a,X).
X = a ;
X = c ;
X = d.

Everything is great ATM, I made PROLOG backtrack all the possible values that comply the goal and(A,B) for A=a. But if I try with the goal nand(A,B):

?- nand(a,X).
false.

Either it thinks that the goal is impossible or it doesn't backtrack, and I haven't got the slightest clue why. :/

Does someone know what I'm doing wrong?

Thanks in advance.

PS: I also tried with:

nand(A,B) :- not(and(A,B)).

And it yields the same result.

EDIT: Seeing that my question is cryptic for some:

I'd like PROLOG to give me a list of values for the variables A and B which make and(A,B) unsatisfiable

EDIT2: I expect PROLOG to tell me:

?- nand(a,X).
    X = e ;
    X = b.

2 Answers2

1

From the SWI-Prolog documentation:

"... True if `Goal' cannot be proven ..."

In other words: \+(and(A, B)) will only succeed if and(A, B) fails. In other words, if there is a solution for and(A, B), \+(and(A, B)) will fail.

From what I see, there is a solution for both and(a, X), and for and(A, B).

Try any query for arguments that are not explicitly declared as is_true/1.

Try to google for "negation as failure", and "closed world assumption". Both have wikipedia articles that are worth reading.

Be careful when you mix boolean logic and Prolog. They don't make the same assumptions.

To your problem: you have a bunch of logical variables. Some of them are true, some of them are false. You want to be able to calculate the truth tables. Say and(A, B) should succeed when the output column is true, and fail otherwise. At this point, you are already mixing up two different concepts:

  1. Logical TRUE and FALSE
  2. Prolog's success and failure

This is actually wrong enough that I would suggest against it. Instead:

and(f, f, f).
and(f, t, f).
and(t, f, f).
and(t, t, t).

not(t, f).
not(f, t).

nand(A, B, R) :- and(A, B, R0), not(R0, R).

val(a, t). val(c, t). val(d, t).
val(b, f). val(e, f).

solve(and(A, B), R) :- val(A, VA), val(B, VB), and(VA, VB, R).
% solve(nand...) as exercise

and so on.

Then, you can have much more informative queries:

?- solve(and(a, c), R).
R = t.

?- solve(and(a, X), R).
X = a,
R = t ;
X = c,
R = t ;
X = d,
R = t ;
X = b,
R = f ;
X = e,
R = f ;
false.

?- solve(nand(a, X), R).
X = a,
R = f ;
X = c,
R = f ;
X = d,
R = f ;
X = b,
R = t ;
X = e,
R = t ;
false.
  • Yes, I've been googling for nearly an hour about negation and negations as failure. I understand your point and it has sense, but I'd like to know a way to achieve what I'm trying to do here, which is making PROLOG backtrack for all the cases in which the goal fails. – Imanol Barba Sabariego Mar 05 '15 at 15:46
  • @ImanolBarbaSabariego Prolog always backtracks if it fails and there are more possible solutions. You have to explicitly stop it from backtracking if you really want to do so. You need to define what it is _actually_ that you are trying to achieve. You don't say in your question what answers you actually expected. –  Mar 05 '15 at 15:49
  • Well, then I don't know how to tell PROLOG to find all the solutions that do not satisfy the goal and(A,X), so again and more precisely: "I'd like a way to tell PROLOG to give me all the results that do not satisfy and(A,B)" – Imanol Barba Sabariego Mar 05 '15 at 15:56
  • @ImanolBarbaSabariego But you are still not saying what these are! Edit your original questio to include the solutions you expect. –  Mar 05 '15 at 15:57
  • Okay: "All the goals that do not satisfy and(A,B) are all of them with which and(A,B) is unsatisfiable" How do I tell PROLOG that? – Imanol Barba Sabariego Mar 05 '15 at 16:00
  • That works but it doesn't solve my question. My question is: Given a goal G given two variables A and B, how do I list all the variables which make the goal fail. The problem is that what I want to achieve is not a boolean solver (for that, PROLOG would be a lousy choice). I have a complex goal defined, which works as expected, and I'd like to list all the values which makes it unsatisfiable because restating the goal would be very cumbersome. The code shown is just a simplification of what I have programmed. – Imanol Barba Sabariego Mar 05 '15 at 16:56
  • 1
    @ImanolBarbaSabariego "all variables" makes no sense. There are infinitely many variable instantiations that can make a goal fail, and only those within its solution space that will make it succeed. You need to at least "existentially qualify" them. –  Mar 05 '15 at 17:06
  • And how is that achieved? Because I thought that declaring them as is_false did qualify them. – Imanol Barba Sabariego Mar 05 '15 at 17:55
1

A simplistic approach would be to introduce a predicate that succeeds for a valid variable. So to your existing predicates, add:

is_valid(X) :- is_true(X) ; is_false(X).

Then the nand/2 predicate can work within that domain and confine the universe of possible values. Otherwise, \+ and(A, B) has no idea what values to choose from to determine failure of and(A, B):

nand(A, B) :- is_valid(A), is_valid(B), \+ and(A, B).

| ?- nand(a, X).

X = b ? ;

X = e ? ;

no

Stated another way, is_valid/1 provides a means for nand/2 to generate the possible options for which \+ and(A, B) can be tested.

You could just as reasonably apply this "confining of the universe" to the other predicates, such as and/2: and(A, B) :- is_valid(A), is_valid(B), is_true(A), is_true(B)., but you can see that this would be redundant.

lurker
  • 56,987
  • 9
  • 69
  • 103