[comp.lang.prolog] forall/2 and negation as failure

reeves@ucla-cs.UUCP (10/22/87)

I'm having a problem reading forall/2 and wondered if anyone  could  help.
In    Sterling    and    Shapiro   p.   270-271,   the   claim   is   that
forall(Goal,Condition) is true for all solutions  of  Goal,  Condition  is
true.  Under this reading not(Goal, not(Condition)) works fine as far as I
can tell.

They claim that

    forall(father(X,C),male(C))

is checking _for_ fathers that have all male children.  My reading is that
it  is  checking  _that_  all  fathers  have  all  male  children.   Their
implementation returns two solutions for the query: the fathers that  have
only  male  children.  In  the database, however, there are fathers who do
not have only male children, so (I would think) the query should fail.

Is there a reading for forall/2 for the following implementation (from S&S)?

	forall(G,C) :- setof(C,G,Cases), check(Cases).

	check([Case|Cases]) :- Case, check(Cases).
	check([]).

Alternatively, is there a case where:

	forall(G,C) :- not(G, not C).

behaves counterintuitively, due to the use of not as negation-as-failure?

Fanx,

  John Reeves
  UCLA CS Department, AI Lab      UUCP: {ihnp4,ucbvax}!ucla-cs!reeves
  3531 Boelter Hall, LA CA 90024  ARPA: reeves@CS.UCLA.EDU

lee@mulga.oz (Lee Naish) (10/26/87)

In article <8781@shemp.UCLA.EDU> reeves@CS.UCLA.EDU (John F. Reeves) writes:
>I'm having a problem reading forall/2 and wondered if anyone  could  help.
>
>    forall(father(X,C),male(C))
>
>....Alternatively, is there a case where:
>
>	forall(G,C) :- not(G, not C).
>
>behaves counterintuitively, due to the use of not as negation-as-failure?
BTW, it should be not (G, not C) or not((G, not C)).

forall has the same problems as \+ (not) in most Prolog systems.
It is not logical.  Even its name has an operational flavor rather than a
declarative one.  It should be logical and be called implies, or =>
(declared as an operator, of course).  Also, there should be a way of
stating the quantification of variables.  In NU-Prolog you can write

all C father(X,C) => male(C)	% all children X fathered are male
or
all X father(X,C) => male(C)	% meaningful but not useful

These are both compiled into the not not form, which delays until the
unquantified variables are ground (hence it is sound).  If the construct
appears in a predicate declared 'pure', further transformation may be
done by the compiler.  For example

all [C,S] (father(X, C), sex(X, S) => S ~= female)
is currently compiled into
all [C,S] not (S = female, father(X, C), sex(X, S))
	(we could do better, of course)

This is all very easy to implement and every Prolog system should have
it (if the system doesnt support delaying then it should write error
messages instead).  It really is useful for programming - it makes
programming easier and programs much more readable.  It is also useful
for teaching.  Here is an game playing example from Bratko (p 360):

win(Pos) :-
	not terminallost(Pos),
	move(Pos, Pos1),
	not ( move(Pos1, Pos2),
	      not won(Pos2)).

The last two lines should be

	all Pos2 move(Pos1, Pos2) => won(Pos2).

Which do you think is easier to understand?

I have just finished teaching an introductory AI/logic programming
course.  For the first time, students have not been (ab)using cut.
Although some of the programming style has not been great (overuse
of if-then-else being the most common flaw), we consider this to be
a significant advance.  A major reason for it is the higher level
logical constructs which are available.   The aggregate functions
(sum, count etc) which Philip Dart mentioned on the network recently
were also used more than I expected.  It seems that they are another
worthwhile logical extension to Prolog.

	lee