TEACH SIR Steven Hardy, November 1982 This TEACH file describes a programming exercise based on the SIR system developed by Bertram Raphael. This is described in: Bertram Raphael SIR: A COMPUTER PROGRAM FOR SEMANTIC INFORMATION RETRIEVAL in SEMANTIC INFORMATION PROCESSING (ed M. Minsky, MIT Press, 1967) Only the bare bones of the project are outlined. You are meant to use your imagination to think up new ways of extending the basic framework. Some suggestion of directions to go in are given at the end. -- A TYPICAL INTERACTION WITH SIR -------------------------------------- : [] -> database; : sir(); ** [SIR IS READY FOR INPUT] ? the capital of england is london ** [OK] ? the mother of john is mary ** [OK] ? what is the capital of england ** [IT IS london] ? what is the capital of france ** [SORRY - I DONT KNOW] ? john is a fireman ** [OK] ? is john a fireman ** [YES] ? every fireman has redbraces ** [OK] ? does john have redbraces ** [YES] ? every fireman is a man ** [OK] ? every thin man is hungry ** [OK] ? john is thin ** [OK] ? is john hungry ** [YES] ? the mother of a hungry man does cook applepie ** [OK] ? who does cook applepie ** [MARY] ? bye ** [SIR IS NOW FINISHED] -- THE BASIC IDEA ------------------------------------------------------ The SIR program can best be described as ELIZA meets DATABASE. One of the exercises in COMPUTERS AND THOUGHT was based on this idea. As with ELIZA, we have a 'master' procedure which controls input and output: define sir(); vars x; [SIR IS READY FOR INPUT] => readline() -> x; until x = [bye] do respondto(x); readline() -> x; enduntil; [SIR IS NOW FINISHED] => enddefine; Where ELIZA has a canned response for each pattern that it matches against the input, SIR has a canned ACTION for each possible input pattern. These actions can, for example, alter the DATABASE or retrieve some information from it. -- A SIMPLE VERSION OF RESPOND ----------------------------------------- define respondto(list); vars x, y, z; if list matches [the ?x of ?y is ?z] then add([the ^x of ^y is ^z]); [OK] => elseif list matches [what is the ?x of ?y] then if present([the ^x of ^y is ?z]) then [IT IS ^z] => else [SORRY - I DONT KNOW] => endif else [SORRY - INPUT NOT UNDERSTOOD] => endif enddefine; The basic form of RESPONDTO is very simple. It tests its argument against a sequence of patterns. When it finds one that matches it then performs some appropriate action. -- AN EXTENSION -------------------------------------------------------- The version of RESPONDTO given above cannot cope with all of the dialogue shown at the start of this TEACH file. Your task is to extend the basic program to move towards making it do so. To help you in this process, here are some suggestions. Consider the following fragment of interaction: ? john is a fireman ** [OK] ? is john a fireman ** [YES] This can be simply handled by editing into RESPONDTO the following lines: elseif list matches [?x is a ?y] then add([^x is a ^y]); [OK] => elseif list matches [is ?x a ?y] then if present([^x is a ^y]) then [YES] => else [NO] => endif To cater for the fragment: ? every fireman has redbraces ** [OK] ? does john have redbraces we would need to edit in: elseif list matches [every ?x has ?y] then add([every ^x has ^y]); [OK] => elseif list matches [does ?x have ?y] then if allpresent([[^x is a ?z] [every ?z has ^y]]) then [YES] => else [NO] => endif Of course, this would not cater for a direct assertion about what JOHN has. The following would still not work: ? john has hair ** [OK] ? does john have hair ** [YES] Notice too that it could not cope with: ? every man has eyes ** [OK] ? does john have eyes ** [YES] which certainly follows from JOHN being a FIREMAN, every FIREMAN being a MAN and every MAN having EYES. Coping with arbitrarily long chains of ISA 'links' (as they are sometimes called) would be a useful extension to the program. -- ADJECTIVES ---------------------------------------------------------- The interation at the start of the section has some examples using adjectives, thus: ? every thin man is hungry ** [OK] ? john is a man ** [OK] ? john is thin ** [OK] ? is john hungry ** [YES] One way to handle this would be to edit in the following lines: elseif list matches [every ?x ?y is ?z] then add([every ^x ^y is ^z]); [OK] => elseif list matches [is ?x ?y] then if present([^x is ^y]) then [YES] => elseif allpresent([[^x is a ?z] [every ?z is a ^y]]) them [YES] => elseif allpresent([[^x is a ?z1] [^x is ?z2] [every ?z1 ?z2 is ^y]]) then [YES] => else [NO] => endif How would this need to be extended if we wanted to handle statements with multiple adjectives, such as the following? ? every tall thin man is underweight ** [OK] -- SUMMARY SO FAR ------------------------------------------------------ The basic idea unerlying this SIR program is that it has a number of patterns for 'matching' input sentences. There is no knowledge of syntax beyond this. Thus we cannot 'capture' the knowledge that, say, nounphrases may include any number of adjectives in one single place but must duplicate it again and again. If we have patterns: [EVERY noun IS A noun] [EVERY noun HAS noun] [EVERY noun IS adjective] and decide to extend our program to allow adjectives before nouns then we must have three completely new patterns, thus: [EVERY adjective noun IS A noun] [EVERY adjective noun HAS noun] [EVERY adjective noun IS adjective] If we wish to allow multiple adjectives, then we need even more patterns. This is an obvious flaw in the design of this type of system. There is another, subtler flaw. The SIR program, as described here (but not the real one written by Raphael), uses ALLPRESENT to make inferences. If the user asks some question then first that question gets matched against one of the patterns and then attempt is made, using ALLPRESENT, to determine the answer to the question. However, there may be several ways of inferring the answer to a question. Consider the question: [IS JOHN A FOOL] The answer to this is YES if any of the following sets of items are in the database: (1) [JOHN IS A FOOL] (2) [JOHN IS A MAN] [EVERY MAN IS A FOOL] (3) [JOHN IS THIN] [JOHN IS A MAN] [EVERY THIN MAN IS A FOOL] (4) [JOHN IS A MAN] [EVERY MAN IS A HUMAN] [EVERY HUMAN IS A FOOL] We must look for each of these potential sets of items explicitly, eg: elseif list matches [is ?x a ?y] then if allpresent([[^x is a ^y]]) or allpresent([[^x is a ?z] [every ?z is a ^y]]) or allpresent([[^x is ?z1] [^x is a ?z2] [every ?z1 ?z2 is a ^y]]) or allpresent( [[^x is a ?z1] [every ?z1 is a ?z2] [every ?z2 is a ^y]]) then [YES] => else [NO] => endif Of course, the problem is that there is an INFINITE number of ways of showing that [?X IS A ?Y] and we could never list them all explicitly as we are trying to do here. Your task in extending the basic SIR framewoprk sketched out above is two fold. Firstly, you should try and make the program as 'clever' as you can within the constraints of the framework. Secondly, you should ponder on the nature of the problems of the basic framework and see if you can come up with some conclusions as to how to improve on it. Obviously, one idea would be to try and incorporate the parsing ideas discussed in ISASENT into SIR. It would be good to have patterns of the form: [EVERY ??x:isaqnoun IS A ?y:isanoun] [EVERY ??x:isaqnoun HAS A ?y:isanoun] The problem is what to do once we have found a match against such a pattern. We may want to have some general translation process that takes us from a structural description of a statement to a representation that facilitates using the information for answering questions. Another idea would be to try and improve the actual retrieval of facts from the database. It seems as if we need an 'inference' package able to cope with the multiple possible ways of answering questions, just as LIB SOLVER copes with the multiple possible actions that may help it to attain its goal. Suppose we restricted ourselves to questions that need only YES or NO answers (ie no WHO type questions), We might have a version of SIR that looked like: define respondto(list); if isaquestion(list) then if prove(list) then [YES] => else [NO] => endif elseif isaassertion(list) then add(list); [OK] => else [EH] => endif enddefine;