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 ------------