// LINNEUS.CL // (C) Copyright 1995 by Steven L. Tanimoto. // This program is described in Chapter 4 ("Knowledge Representation") of // "The Elements of Artificial Intelligence Using Common Lisp," 2nd ed., // published by W. H. Freeman, 41 Madison Ave., New York, NY 10010. // Permission is granted for noncommercial use and modification of // this program, provided that this copyright notice is retained // and followed by a notice of any modifications made to the program. // The function LINNEUS embodies the main loop. define method linneus () // Top-level loop for interaction with LINNEUS. format-out("(THIS IS LINNEUS. PLEASE TALK TO ME)\n"); block (return) while (#t) format-out("--> "); // Print prompt symbol. if (interpret(// LTD: Function READ not yet implemented. read()) == #"bye") return(#(#"goodbye")); end if; end while; end block; end method linneus; // INTERPRET contains the production rules. define method interpret (text) // Applies production rules embedded in a COND form to // interpret and process the user's input sentence. let _that = #f; if (_that := handle-assertion(text)) _that; elseif (_that := handle-what-is(text)) _that; elseif (_that := handle-is-a(text)) _that; elseif (_that := handle-why(text)) _that; // rule for session termination: elseif (match(#(#"bye"), text)) #"bye"; // rule for all other inputs: else answer(#(#"i", #"do", #"not", #"understand")); end if; end method interpret; define method answer (answer-list) // Prints out the answer and returns T. print(answer-list, *standard-output*); write-element(*standard-output*, '\n'); #t; end method answer; define method handle-assertion (text) // Tests for and handles assertion of fact by the user. let b = match(#(#(#"match-article", #"article1"), #(#"?", #"x"), #"is", #(#"match-article", #"article2"), #(#"?", #"y")), text); if (b) let x = val(#"x", b); let y = val(#"y", b); let article1 = val(#"article1", b); let article2 = val(#"article2", b); add-superset(x, y); add-subset(y, x); set-article(x, article1); set-article(y, article2); answer(#(#"i", #"understand")); end if; end method handle-assertion; define method handle-what-is (text) // Tests for and handles questions e.g., (WHAT IS A DOG). block (return-from-handle-what-is) let b = match(#(#"what", #"is", #(#"match-article", #"article1"), #(#"?", #"x")), text); let isaflag = #f; let includeflag = #f; if (b) let x = val(#"x", b); let y = val(#"y", b); if (y := get-isa(x)) isaflag := #t; elseif (y := get-includes(x)) includeflag := #t; else format-out("(I DON'T KNOW)\n"); return-from-handle-what-is(#t); end if; answer(concatenate(list(get-article(x)), list(x), if (isaflag) #(#"is"); else #(#"is", #"something", #"more", #"general", #"than"); end if, make-conj(y))); end if; end block; end method handle-what-is; define method handle-is-a (text) // Tests for and handles queries of the form (IS A DOG AN ANIMAL). let b = match(#(#"is", #(#"match-article", #"article1"), #(#"?", #"x"), #(#"match-article", #"article2"), #(#"?", #"y")), text); if (b) let x = val(#"x", b); let y = val(#"y", b); if (isa-test(x, y, 10)) answer(concatenate(#(#"yes", #"indeed"), tell(x, y))); else answer(#(#"sorry", #"not", #"that", #"i", #"know", #"of")); end if; end if; end method handle-is-a; define method handle-why (text) // Tests for and handles WHY questions. let b = match(#(#"why", #"is", #(#"match-article", #"article1"), #(#"?", #"x"), #(#"match-article", #"article2"), #(#"?", #"y")), text); if (b) let x = val(#"x", b); let y = val(#"y", b); if (isa-test(x, y, 10)) answer(pair(#"because", explain-links(x, y))); else answer(#(#"but", #"as", #"far", #"as", #"i", #"know", #"it", #"is", #"not!")); end if; end if; end method handle-why; // Create hash tables to store the knowledge // base components, and define the functions // for storing and retrieving knowledge. begin let isa-base = make(