[comp.lang.prolog] elementary problem

ccsdgdc@gdr.bath.ac.uk (Douglas Clark) (03/09/90)

A user has been asking me how to write synonyms in Prolog. Being ignorant
I have no idea. It is obvious why the natural

father(X):-male(X).
male(X):-father(X).
father(fred).

fails. But I cannot find a substute that works. Some way of eliminating
the repetitive backtracking. Help would be appreciated.
-- 
Douglas Clark                                   Voice : +44 225 826039
User Services,                            JANET : ccsdgdc@uk.ac.bath.gdr
Bath University Computing Services,  UUCP : uunet!mcsun!ukc!gdr!ccsdgdc
Bath, Avon, England BA2 7AY     ARPA : ccsdgdc%gdr.bath.ac.uk@nsfnet-relay.ac.uk

feldman@Neon.Stanford.EDU (Todd J. Feldman) (03/10/90)

In article <1990Mar9.095655.4191@bath.ac.uk> ccsdgdc@gdr.bath.ac.uk (Douglas Clark) writes:
>
>A user has been asking me how to write synonyms in Prolog. Being ignorant
>I have no idea. It is obvious why the natural
>
>father(X):-male(X).
>male(X):-father(X).
>father(fred).
>
>fails. But I cannot find a substute that works. Some way of eliminating
>the repetitive backtracking. Help would be appreciated.

How about:

father(X):-
	not(tried(male(X))),
	assert(tried(male(X))),
	male(X).
male(X):-
	not(tried(father(X))),
	assert(tried(father(X))),
	father(X).

if you store any 'male' or 'father' facts, they will be detected, and any
infinite recursion will be prevented by the 'tried' facts.  Of course, you'd
need to be sure to clean up these 'tried' facts when you're done.


Todd

ok@goanna.oz.au (Richard O'keefe) (03/12/90)

In article <1990Mar9.095655.4191@bath.ac.uk>
ccsdgdc@gdr.bath.ac.uk (Douglas Clark) writes:
>A user has been asking me how to write synonyms in Prolog.
>Being ignorant I have no idea.
>It is obvious why the natural

>father(X) :- male(X).
>male(X) :- father(X).
>father(fred).

>fails.  But I cannot find a substitute that works.  Some way of eliminating
>the repetitive backtracking.  Help would be appreciated.

Er, what repetitive backtracking?  The code exhibited must go into an
infinite loop without ever delivering any answers:
	?- father(tom)
    =>	?- male(tom)
    =>	?- father(tom)
and away we go.  

Do you really believe that "father" and "male" are synonyms?  Strange world.

If you have two predicates p and q such that p iff and only if q, then all
you have to do is to pick one of them, say p, and decide to take it as basic.
What you do is include the axiom
	q(X) :- p(X).
If this is the only clause for q, then p and q cannot possibly differ at
any point.  YOU DON'T NEED TO DO ANYTHING TO P TO MAKE THIS SO.

It's a good idea to make the definition of p self-contained, so whenever
you would have called q in the definition of p, make it call p instead.
That isn't strictly necessary.

In this particular example, to make sure that father/1 and male/1 have
exactly the same set of answers, and that fred is a father, it suffices
to write

	male(X) :- father(X).		% make male, father equivalent

	father(fred).			% define father

In article <1990Mar10.120125.12992@Neon.Stanford.EDU>, 
feldman@Neon.Stanford.EDU (Todd J. Feldman) writes:
> How about:
 
> father(X):-
> 	not(tried(male(X))),
> 	assert(tried(male(X))),
> 	male(X).
> male(X):-
> 	not(tried(father(X))),
> 	assert(tried(father(X))),
> 	father(X).

This does not work at all if you ask a question with a variable in it.
Suppose I ask
	?- male(fred), male(X).
Given the fact father(fred), this should succeed with X = fred.

The greatest problem with Feldman's approach is its use of the data base.

	father(fred).
	father(X) :- subgoal_of(father(X)), !, fail.
	father(X) :- male(X).

	male(X) :- subgoal_of(male(X)), !, fail.
	male(X) :- father(X).

doesn't leave a lot of dangerous mess around behind it.  It has problems
of its own.  (See discussions of the "loop check problem".)  An approach
which might work rather nicely would be to use extension tables.

But the simplest approach is just not to put the loop there in the first
place.

kemp@cs.mu.oz.au (David Barry Kemp) (03/12/90)

ok@goanna.oz.au (Richard O'keefe) writes:

(The original question...)
>In article <1990Mar9.095655.4191@bath.ac.uk>
>ccsdgdc@gdr.bath.ac.uk (Douglas Clark) writes:
>>A user has been asking me how to write synonyms in Prolog.
>>Being ignorant I have no idea.
>>It is obvious why the natural

>>father(X) :- male(X).
>>male(X) :- father(X).
>>father(fred).

>>fails.  But I cannot find a substitute that works.  Some way of eliminating
>>the repetitive backtracking.  Help would be appreciated.

(Richard's suggestion)
>If you have two predicates p and q such that p iff and only if q, then all
>you have to do is to pick one of them, say p, and decide to take it as basic.
>What you do is include the axiom
>	q(X) :- p(X).
>If this is the only clause for q, then p and q cannot possibly differ at
>any point.  YOU DON'T NEED TO DO ANYTHING TO P TO MAKE THIS SO.

>.....

>In this particular example, to make sure that father/1 and male/1 have
>exactly the same set of answers, and that fred is a father, it suffices
>to write

>	male(X) :- father(X).		% make male, father equivalent

>	father(fred).			% define father

NOTE: If you have facts (unit clauses) for both male and father,
then the database will need to be re-arranged so that all of them are
stored as facts for father only.
BUT If you already have code that asserts or retracts facts for male,
then these will all need to be changed to asserts/retracts for father.
Todd Feldman's solution almost avoids this, except for an important
point given by Richard.

>In article <1990Mar10.120125.12992@Neon.Stanford.EDU>, 
>feldman@Neon.Stanford.EDU (Todd J. Feldman) writes:
>> How about:
> 
>> father(X):-
>> 	not(tried(male(X))),
>> 	assert(tried(male(X))),
>> 	male(X).
>> male(X):-
>> 	not(tried(father(X))),
>> 	assert(tried(father(X))),
>> 	father(X).

(Richard's comment)
>This does not work at all if you ask a question with a variable in it.
>Suppose I ask
>	?- male(fred), male(X).
>Given the fact father(fred), this should succeed with X = fred.

>...

> ...An approach
> which might work rather nicely would be to use extension tables.

>But the simplest approach is just not to put the loop there in the first
>place.

I agree.  However, if you really did want the two predicates to become
equivalent, then the original suggestion of adding the rules

father(X):-male(X).
male(X):-father(X).

would have worked exactly as you intended on one of the deductive database
systems currently appearing/being developed that use minimal model semantics,
since what you really wanted is the minimum model that satisfies these rules
along with the database of male and father facts.  To efficiently evaluate
queries and avoid infinite loops, the extension tables that Richard refers
to may be used (there is a lot of research into finding even better methods).

------------
David B. Kemp
Key Centre for Knowledge Base Systems
Department of Computer Science
University of Melbourne
Parkville 3052
Australia

e_mail: kemp@cs.mu.OZ.AU
Telephone: 61 3 344 7877
Fax: 61 3 348 1184
------------