home *** CD-ROM | disk | FTP | other *** search
/ NeXT Education Software Sampler 1992 Fall / NeXT Education Software Sampler 1992 Fall.iso / Programming / Source / winterp-1.13 / examples / xlisp-2.1 / qa.lsp < prev    next >
Encoding:
Text File  |  1991-10-06  |  37.8 KB  |  1,272 lines

  1. ; -*-Lisp-*-
  2. ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
  3. ;
  4. ; File:         qa.lsp
  5. ; RCS:          $Header: $
  6. ; Description:  qa.lsp - Question answering program using set-of-support
  7. ;        unit-preference resolution principles.
  8. ; Author:       John W. Ward (jwward) for XLISP 1.7
  9. ;        Converted to XLISP 2.0 by David Betz.
  10. ; Created:      06-Dec-86
  11. ; Modified:     Sat Oct  5 21:16:19 1991 (Niels Mayer) mayer@hplnpm
  12. ; Language:     Lisp
  13. ; Package:      N/A
  14. ; Status:       X11r5 contrib tape release
  15. ;
  16. ; WINTERP Copyright 1989, 1990, 1991 Hewlett-Packard Company (by Niels Mayer).
  17. ; XLISP version 2.1, Copyright (c) 1989, by David Betz.
  18. ;
  19. ; Permission to use, copy, modify, distribute, and sell this software and its
  20. ; documentation for any purpose is hereby granted without fee, provided that
  21. ; the above copyright notice appear in all copies and that both that
  22. ; copyright notice and this permission notice appear in supporting
  23. ; documentation, and that the name of Hewlett-Packard and Niels Mayer not be
  24. ; used in advertising or publicity pertaining to distribution of the software
  25. ; without specific, written prior permission.  Hewlett-Packard and Niels Mayer
  26. ; makes no representations about the suitability of this software for any
  27. ; purpose.  It is provided "as is" without express or implied warranty.
  28. ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
  29.  
  30. ;========================================================================
  31. ;
  32. ;   qa.lsp - Question answering program using set-of-support
  33. ;            unit-preference resolution principles.
  34. ;
  35. ;   Author: John W. Ward (jwward)
  36. ;   Date:   06-Dec-86
  37. ;
  38. ;       The following program was written for an Artificial Intelligence
  39. ;   class at Kent State University.  The testing sequence used was designed
  40. ;   specifically to fit class requirements.  The program is offered for
  41. ;   inspection and experimentation.  The only claim I make regarding the
  42. ;   program is that I enjoyed working on it and learned something from it.
  43. ;
  44. ;       Some of the algorithms and examples follow our textbook: Artificial
  45. ;   Intelligence, by Elaine Rich (McGraw-Hill, 1983).
  46. ;
  47. ;-------------------------------------------------------------------------
  48. ;
  49. ;       Known limitations: The program degrades quickly when there is
  50. ;   a relatively high branching factor (i.e. many possible paths).  When
  51. ;   the pairs variable gets too big, something nasty usually happens.  On
  52. ;   my machine the something nasty is a warm restart.
  53. ;
  54. ;       The program was written in XLISP 1.7.  Converted to XLISP 2.0
  55. ;   by David Betz.
  56. ;
  57. ;-------------------------------------------------------------------------
  58. ;   QA.LOG provides a transcript of a program session.
  59. ;-------------------------------------------------------------------------
  60. ;
  61. ;   Question-answering is done as follows:
  62. ;   1) The question is negated, then converted to clause form with the
  63. ;      original question tacked on in a $SUCCESS$ "literal".
  64. ;   2) Each clause of the question is paired with all members of base,
  65. ;      producing the original "pairs" list.  Insertion to the list are
  66. ;      according to size of smaller clause * 1000 + size of larger clause.
  67. ;      Each clause is then added to the "base", which thus contains the
  68. ;      set-of-support as well.
  69. ;   3) Until solution is found (and user specifies QUIT) or "pairs" is
  70. ;      exhausted or the number of pairs tested exceeds a set limit (400):
  71. ;      a) Take the next pair of clauses from "pairs".  Try to resolve by
  72. ;         attempting to unify any pair of literals having opposite sign.
  73. ;      b) If the unification is successful, produce the resolution.
  74. ;         If resolution produces a clause already in the base, ignore it.
  75. ;         Otherwise, if the resolution is a success state, display and
  76. ;            ask the user for MORE or QUIT.
  77. ;         Otherwise (new, non-success result), add the result paired with
  78. ;            all current members of the base cum set-of-support to "pairs",
  79. ;            then add the result to the base.
  80. ;
  81. ;   Practically, this thing is slow and perverse.  It's amazing how long
  82. ;   it takes to exhaust the possibilities of an obviously wrong path.
  83. ;
  84. ;   Data structures and variables:
  85. ;       base            - List of hypotheses and set-of-support. The
  86. ;                         set-of-support can be distinguished by a $success$
  87. ;                         clause.  Each clause is actually a list, with the
  88. ;                         clause proceeded by its literal-count.
  89. ;       pairs           - List of clause-pairs to consider for resolution.
  90. ;                         Entries are triples - combined literal-count,
  91. ;                         left-clause and right-clause.  Sorted on ascending
  92. ;                         literal-count, with new entries following old ones
  93. ;                         to provide results analogous to a breadth-first
  94. ;                         search.  (New preceding old ends up close to depth-
  95. ;                         first.)
  96. ;       q-clause        - S-o-s clause currently under consideration (LHS)
  97. ;       b-clause        - Base clause currently under consideration (RHS)
  98. ;       subst-list      - Composition of all substitutions used in
  99. ;                         resolution.  This can be applied to the
  100. ;                         query to produce a solution.  (I hope!)
  101. ;       names           - Names in use in the base including variable names,
  102. ;                         predicates, and Skolem functions.  The type of
  103. ;                         each name will be attached to it.
  104. ;                         (I will convert variables on initial entry into
  105. ;                         the base or query, thus avoiding renaming later.
  106. ;                         I hope!)
  107. ;
  108. ;   Naming:
  109. ;       Constants       - begin with letters A through F or with $.
  110. ;                         (XLISP converts input to upper-case, so I can't
  111. ;                         distinguish that way.)
  112. ;       Variables       - Begin with G through Z.
  113. ;
  114. ;       Associate with every element of a clause is its type - CONSTANT or
  115. ;           VARIABLE.
  116. ;
  117. ;=========================================================================
  118. ;
  119. (alloc 1000)
  120. (expand 20)
  121. ;
  122. ;-------------------------------------------------------------------
  123. ;
  124. ;   qa - main routine
  125. ;
  126. ;   The program is in assert or question mode.  In question mode,
  127. ;       it will attempt to answer the question given by the user.  In
  128. ;       assert mode, it will add to the fact base.
  129. ;
  130. ;   Special commands:
  131. ;       assert    - Change to assert mode
  132. ;       question  - Change to question mode
  133. ;       end       - Start with a new base of information
  134. ;       nil       - End the program
  135. ;
  136. ;-------------------------------------------------------------------
  137. (defun qa ()
  138.     ; First time
  139.     (init-qa)
  140.  
  141.     ; Main loop for each base set
  142.     (do
  143.         ()  ; No initialization
  144.         ((or (null in-line) (equal in-line 'end)))
  145.  
  146.         (setq in-line (get-input mode))
  147.         (cond
  148.             ((null in-line) nil)
  149.             ((equal in-line 'end) (init-qa))
  150.             ((equal in-line 'assert) (setq mode in-line))
  151.             ((equal in-line 'question) (setq mode in-line))
  152.             ((equal in-line 'base)
  153.                 (mapcar `(lambda (a) (print (cadr a))) base)
  154.             )
  155.             ((equal in-line 'proof)
  156.                 (setq show-proof (not show-proof))
  157.                 (cond
  158.                     (show-proof (princ "Resolutions will be shown.\n"))
  159.                     (t (princ "Only answers will be shown.\n"))
  160.                 )
  161.             )
  162.             ((equal in-line 'unify)
  163.                 (setq show-unify (not show-unify))
  164.                 (cond
  165.                     (show-unify (princ "Unifications will be shown.\n"))
  166.                     (t (princ "Unifications will not be shown.\n"))
  167.                 )
  168.             )
  169.             ((equal in-line 'pairs)
  170.                 (setq show-pairs (not show-pairs))
  171.                 (cond
  172.                     (show-pairs (princ "Clause-pairs will be shown.\n"))
  173.                     (t (princ "Clause-pairs will be shown.\n"))
  174.                 )
  175.             )
  176.             ((equal in-line 'help) (give-help))
  177.             ((equal mode 'question) (answer in-line))
  178.             (t (assume in-line))
  179.         )
  180.     )
  181. )
  182. ;
  183. ;-------------------------------------------------------------------
  184. ;
  185. ;   Provide simple help messages
  186. ;
  187. (defun give-help ()
  188.     (princ "\n\n\tQA - Help\n\n")
  189.     (princ "Commands:\n")
  190.     (princ "\tNil to exit, End to restart\n")
  191.     (princ "\tProof, Unify, and Pairs toggle display settings\n")
  192.     (princ "\tAssert      - Shift to assertion mode\n")
  193.     (princ "\tQuestion    - Shift to question mode\n")
  194.     (princ "\tBase        - Display base assumptions\n")
  195.     (princ "\tHelp        - Print this message\n")
  196.     (princ "\nInput form:\n\n")
  197.     (princ "\tConstants begin with letters A-E or $.\n\n")
  198.     (princ "\tEnter assertions or questions in LISP-like form.  You may\n")
  199.     (princ "include the operators AND, OR, NOT, IMPLY, AND EQUIV.  Thus,\n")
  200.     (princ "to indicate that a male parent is a father, type:\n\n")
  201.     (princ "\t(EQUIV (AND ($PARENT X Y) ($MALE X)) ($FATHER X Y))\n\n")
  202.     (princ "The definition of commutative binary operations is:\n\n")
  203.     (princ "\t(IMPLY ($COMMUT K) (EQUIV (K X Y Z) (K Y X Z)))\n")
  204. )
  205. ;-------------------------------------------------------------------
  206. ;
  207. ;   Attempt to answer the question
  208. ;
  209. (defun answer (question)
  210.     (let
  211.         (
  212.             (c-question nil)
  213.         )
  214.         (setq pairs nil)
  215.         (setq
  216.             c-question
  217.             (clause-convert `(or (not ,question) ($success$ ,question)))
  218.         )
  219.         (cond
  220.             ((equal (car c-question) 'and)
  221.                 (setq c-question (mapcar 'set-types c-question))
  222.                 (mapcar 'add-sos (cdr c-question))
  223.             )
  224.             (t
  225.                 (setq c-question (set-types c-question))
  226.                 (add-sos c-question)
  227.             )
  228.         )
  229.         (solve)
  230.         (princ "\n\nDone.\n\n")
  231.         (setq base (remove-success base))
  232.     )
  233. )
  234. ;
  235. ;-------------------------------------------------------------------
  236. ;
  237. ;   Find solution to the question -
  238. ;
  239. ;
  240. ;   pairs = (question X base) from set-up
  241. ;   done <-- nil
  242. ;   While pairs != nil and done == nil {
  243. ;       pair <-- (car pairs); pairs <-- (cdr pairs);
  244. ;       Get q-clause and b-clause from pair
  245. ;           <<< solve-clause-clause >>>
  246. ;           For each q-literal in q-clause {
  247. ;               <<< solve-lit-clause >>>
  248. ;               For each b-literal of opposite sign in b-clause {
  249. ;                   <<< solve-lit-lit >>>
  250. ;                   subs <-- unification of q-literal and b-literal
  251. ;                   If subs != nil {
  252. ;                       Make subs in q-clause and b-clause
  253. ;                       resolution <-- resolve of q-clause and b-clause
  254. ;                       <<< resolved >>>
  255. ;                           Report resolution
  256. ;                           If resolution is a success-state {
  257. ;                               return true if they don't want More
  258. ;                           }
  259. ;                           else {
  260. ;                               add (resolution X base) to pairs
  261. ;                               add resolution to base
  262. ;                               return nil (keep going)
  263. ;                           }
  264. ;                   }
  265. ;               }
  266. ;           }
  267. ;   }
  268. ;
  269. ;
  270. (defun solve ()
  271.     (setq solutions-found nil)
  272.     (setq pairs-count 0)
  273.     (do
  274.         (
  275.             (done nil)
  276.             (pair nil)
  277.         )
  278.         (
  279.             (or done (null pairs) (>= pairs-count max-pairs))
  280.         )
  281.         (setq pair (car pairs))
  282.         (setq pairs (cdr pairs))
  283.  
  284.         (setq q-clause (cadr pair))
  285.         (setq b-clause (caddr pair))
  286.  
  287.         (setq done (solve-clause-clause))
  288.     )
  289. )
  290. ;-------------------------------------------------------------------
  291. ;
  292. ;   Test if result is a success
  293. ;
  294. ;
  295. (defun success-p (clause)
  296.     (cond
  297.         ((atom clause) nil)
  298.         ((equal (car (first-lit clause)) '$success$) t)
  299.         (t nil)
  300.     )
  301. )
  302. ;-------------------------------------------------------------------
  303. ;
  304. ;   Solve given two clauses - pass on with full clauses for later
  305. ;       breakup
  306. ;
  307. ;           <<< solve-clause-clause >>>
  308. ;           Add b-clause to right-used
  309. ;           For each q-literal in q-clause {
  310. ;               <<< solve-lit-clause >>>
  311. ;           }
  312. ;
  313. (defun solve-clause-clause ()
  314.     (cond
  315.         (show-pairs
  316.             (princ "Working on clauses:\n")
  317.             (print q-clause)
  318.             (print b-clause)
  319.             (terpri)
  320.         )
  321.     )
  322.     (setq pairs-count (1+ pairs-count))
  323.     (cond
  324.         ((equal (rem pairs-count 50) 0)
  325.             (princ "Pairs count:\t") (print pairs-count)
  326.             (princ "Base:\t\t")  (print (length base))
  327.             (princ "Pairs:\t\t") (print (length pairs))
  328.             (princ "Size:\t\t")  (print (deep-count pairs))
  329.             (terpri)
  330.             (gc)
  331.             (mem)
  332.             (terpri)
  333.         )
  334.     )
  335.  
  336.     (solve-clause-clause* (remove-success q-clause) (remove-success b-clause))
  337. )
  338. (defun solve-clause-clause* (q-work b-work)
  339.     (let
  340.         (
  341.             (result nil)
  342.         )
  343.         (cond
  344.             ((null b-work) nil)
  345.             ((atom b-work)
  346.                 (princ "Error in solve-clause-clause* - b-work is atom\n")
  347.                 nil
  348.             )
  349.             ((null q-work) nil)
  350.             ((atom q-work)
  351.                 (princ "Error in solve-clause-clause* - q-work is atom\n")
  352.                 nil
  353.             )
  354.             (
  355.                 (setq result (solve-lit-clause (first-lit q-work) b-work))
  356.                 result
  357.             )
  358.             (t (solve-clause-clause* (remove-first-lit q-work) b-work))
  359.         )
  360.     )
  361. )
  362. ;-------------------------------------------------------------------
  363. ;
  364. ;   Solve with a question literal and a base clause
  365. ;
  366. ;               <<< solve-lit-clause >>>
  367. ;               For each b-literal of opposite sign in b-clause {
  368. ;                   <<< solve-lit-lit >>>
  369. ;               }
  370. ;
  371. ;
  372. (defun solve-lit-clause (q-lit b-work)
  373.     (let
  374.         (
  375.             (result nil)
  376.         )
  377.         (cond
  378.             ((null q-lit) nil)
  379.             ((atom q-lit)
  380.                 (princ "Error in solve-lit-clause - q-lit is atom\n")
  381.                 nil
  382.             )
  383.             ((null b-work) nil)
  384.             ((atom b-work)
  385.                 (princ "Error in solve-lit-clause - b-work is atom\n")
  386.                 nil
  387.             )
  388.             ((setq result (solve-lit-lit q-lit (first-lit b-work))) result)
  389.             (t (solve-lit-clause q-lit (remove-first-lit b-work)))
  390.         )
  391.     )
  392. )
  393. ;-------------------------------------------------------------------
  394. ;
  395. ;   Solve with a question literal and a base literal
  396. ;
  397. ;                   <<< solve-lit-lit >>>
  398. ;                   subs <-- unification of q-literal and b-literal
  399. ;                   If subs != nil {
  400. ;                       Make subs in q-clause and b-clause
  401. ;                       resolution <-- resolve of q-clause and b-clause
  402. ;                       If resolution != nil {
  403. ;                           <<< resolved >>>
  404. ;                       }
  405. ;                   }
  406. ;
  407. ;
  408. (defun solve-lit-lit (q-lit b-lit)
  409.     (let
  410.         (
  411.             (subs nil)
  412.             (resolution nil)
  413.             (old-q q-clause)
  414.             (old-b b-clause)
  415.         )
  416.  
  417.         ; Quit without effort if literals are not of opposite sign
  418.         (cond
  419.             ((equal (lit-sign q-lit) (lit-sign b-lit)) nil)
  420.             (t
  421.                 (setq subs (unify q-lit b-lit))
  422.                 (cond
  423.                     (show-unify
  424.                         (princ "Unification of: ") (print q-lit)
  425.                         (princ "           and: ") (print b-lit)
  426.                         (princ "            is: ") (print subs)
  427.                         (terpri)
  428.                     )
  429.                 )
  430.                 (cond
  431.                     ((not (null subs))
  432.                         (setq old-q (make-subs subs q-clause))
  433.                         (setq old-b (make-subs subs b-clause))
  434.                         (setq resolution (resolve old-q old-b))
  435.                         (cond
  436.                             (
  437.                                 (not
  438.                                     (member
  439.                                         (add-count resolution)
  440.                                         base :test #'equal
  441.                                     )
  442.                                 )
  443.                                 (resolved resolution)
  444.                             )
  445.                             (t nil)
  446.                         )
  447.                     )
  448.                     (t nil)
  449.                 )
  450.             )
  451.         )
  452.     )
  453. )
  454. ;-------------------------------------------------------------------
  455. ;
  456. ;   Handle a successful resolution
  457. ;
  458. ;                           Report resolution
  459. ;                           If resolution is a success-state {
  460. ;                               done <-- quit if they don't want More
  461. ;                           }
  462. ;                           else {
  463. ;                               add (resolution X base) to pairs
  464. ;                               add resolution to base
  465. ;                               return nil for resolution
  466. ;                           }
  467. ;
  468. (defun resolved (resolution)
  469.     (cond
  470.         (show-proof
  471.             (terpri)
  472.             (princ "Clause 1   ") (print q-clause)
  473.             (princ "Clause 2   ") (print b-clause)
  474.             (princ "Resolution ") (print resolution)
  475.             (terpri)
  476.         )
  477.     )
  478.     (cond
  479.         ((success-p resolution)
  480.             (cond
  481.                 (
  482.                     (not
  483.                         (member
  484.                             resolution
  485.                             solutions-found :test #'equal
  486.                         )
  487.                     )
  488.                     (setq
  489.                         solutions-found
  490.                         (append solutions-found (list resolution))
  491.                     )
  492.                     (print (first-lit resolution))
  493.                     (terpri)
  494.                     (princ "Enter QUIT to quit, MORE for more solutions --")
  495.                     (equal (read) 'quit)
  496.                 )
  497.                 (t nil)
  498.             )
  499.         )
  500.         (t
  501.             (add-sos resolution)
  502.             nil
  503.         )
  504.     )
  505. )
  506. ;-------------------------------------------------------------------
  507. ;
  508. ;   Determine sign of literal (either NOT or NIL)
  509. ;
  510. ;
  511. (defun lit-sign (lit)
  512.     (cond
  513.         ((atom lit) nil)
  514.         ((equal (car lit) 'not) 'not)
  515.         (t nil)
  516.     )
  517. )
  518. ;-------------------------------------------------------------------
  519. ;
  520. ;   Return the "absolute value" (NOT removed) of lit
  521. ;
  522. ;
  523. (defun lit-abs (lit)
  524.     (cond
  525.         ((null (lit-sign lit)) lit)
  526.         (t (cadr lit))
  527.     )
  528. )
  529. ;-------------------------------------------------------------------
  530. ;
  531. ;   Return the negation of a literal
  532. ;
  533. ;
  534. (defun lit-negative (lit)
  535.     (cond
  536.         ((null (lit-sign lit)) `(not ,lit))
  537.         (t (cadr lit))
  538.     )
  539. )
  540. ;-------------------------------------------------------------------
  541. ;
  542. ;   Unify two literals - (from the book, page 156)
  543. ;
  544. ;
  545. (defun unify (q-lit b-lit)
  546.     (unify* (lit-abs q-lit) (lit-abs b-lit) nil)
  547. )
  548. (defun unify* (q-lit b-lit subs)
  549.     (cond
  550.         ; If either is an atom, they must be equal or
  551.         ;       at least one a variable, else fail
  552.         ((or (atom q-lit) (atom b-lit))
  553.             (cond
  554.                 ((equal q-lit b-lit) (compose subs '(nil nil)))
  555.                 ((variable-p b-lit) (compose subs (ok-sub b-lit q-lit)))
  556.                 ((variable-p q-lit) (compose subs (ok-sub q-lit b-lit)))
  557.                 (t nil)
  558.             )
  559.         )
  560.  
  561.         ; We get here for lists
  562.         ((/= (length q-lit) (length b-lit)) nil)
  563.         (t
  564.             (setq subs (unify* (car q-lit) (car b-lit) subs))
  565.             (cond
  566.                 ((null subs) nil)
  567.                 (t
  568.                     (unify*
  569.                         (make-subs subs (cdr q-lit))
  570.                         (make-subs subs (cdr b-lit))
  571.                         subs
  572.                     )
  573.                 )
  574.             )
  575.         )
  576.     )
  577. )
  578. ;-------------------------------------------------------------------
  579. ;
  580. ;   Return nil if y contains x, else return (x y)
  581. ;
  582. ;
  583. (defun ok-sub (x y)
  584.     (cond
  585.         ((deep-member x y) nil)
  586.         (t `(,x ,y))
  587.     )
  588. )
  589. ;-------------------------------------------------------------------
  590. ;
  591. ;   Compose single substitution y into list x
  592. ;
  593. ;
  594. (defun compose (x y)
  595.     (let
  596.         (
  597.             (result nil)
  598.         )
  599.         (cond
  600.             ((null y) nil)
  601.             ((null x) (list y))
  602.             ((equal x '((nil nil))) (list y))
  603.             (t
  604.                 (setq x (sub-right-side y x))
  605.                 (cond
  606.                     ((assoc (car y) x) x)
  607.                     (t (append x (list y)))
  608.                 )
  609.             )
  610.         )
  611.     )
  612. )
  613. ;-------------------------------------------------------------------
  614. ;
  615. ;   Make all substitutions sub (a b) into substitution list
  616. ;       of the form ((x a)) --> ((x b))
  617. ;
  618. ;
  619. (defun sub-right-side (sub sub-list)
  620.     (mapcar `(lambda (x) (sub-right-side* ',sub x)) sub-list)
  621. )
  622. (defun sub-right-side* (sub sub-entry)
  623.     (cons
  624.         (car sub-entry)
  625.         (make-subs (list sub) (cdr sub-entry))
  626.     )
  627. )
  628. ;-------------------------------------------------------------------
  629. ;
  630. ;   Is x variable?
  631. ;
  632. ;
  633. (defun variable-p (x)
  634.     (cond
  635.         ((null x) nil)
  636.         ((atom x) (equal (get x 'type) 'variable))
  637.         (t nil)
  638.     )
  639. )
  640. ;-------------------------------------------------------------------
  641. ;
  642. ;   Resolve two unified clauses
  643. ;
  644. ;
  645. (defun resolve (clause-1 clause-2)
  646.     (let
  647.         (
  648.             (result nil)
  649.         )
  650.         (setq success-list '(or))
  651.         (setq clause-1 (strip-success clause-1))
  652.         (setq clause-2 (strip-success clause-2))
  653.  
  654.         (setq result (load-lits (lit-factor clause-1) '(or)))
  655.         (setq result (load-lits (lit-factor clause-2) result))
  656.         (setq result (load-lits success-list result))
  657.         result
  658.     )
  659. )
  660. ;-------------------------------------------------------------------
  661. ;
  662. ;   Return clause less all $success$ literals and record $success$
  663. ;       literals in success-list
  664. ;
  665. ;
  666. (defun strip-success (clause)
  667.     (cond
  668.         ((null clause) nil)
  669.         ((atom clause) nil)     ; Should be an error
  670.         ((equal (car clause) '$success$)
  671.             (setq success-list (load-lits clause success-list))
  672.             nil
  673.         )
  674.         ((literal-p clause) clause)
  675.         (t                              ; Begins with OR
  676.             (remove
  677.                 nil
  678.                 (cons (car clause) (mapcar 'strip-success (cdr clause)))
  679.             )
  680.         )
  681.     )
  682. )
  683. ;-------------------------------------------------------------------
  684. ;
  685. ;   Before we turn the clauses loose on each other, factor any
  686. ;   internally repeated literals.  If there are internal opposite
  687. ;   literals, return nil, thus letting the other clauses be unaffected
  688. ;   by the tautology.
  689. ;
  690. ;
  691. (defun lit-factor (clause)
  692.     (lit-factor* clause '(or))
  693. )
  694. (defun lit-factor* (clause new-clause)
  695.     (let
  696.         (
  697.             (first (first-lit clause))
  698.             (rest (remove-first-lit clause))
  699.         )
  700.         (cond
  701.             ((null clause) new-clause)
  702.             ((member first new-clause :test #'equal)
  703.                 (lit-factor* rest new-clause)
  704.             )
  705.             ((member (lit-negative first) new-clause :test #'equal) nil)
  706.             (t (lit-factor* rest (append new-clause (list first))))
  707.         )
  708.     )
  709. )
  710. ;-------------------------------------------------------------------
  711. ;
  712. ;   Add literals to clause -
  713. ;       If literal's negative is in clause, remove from both clauses
  714. ;       If literal is in clause, don't add it.
  715. ;       Otherwise add at end of clause
  716. ;
  717. ;
  718. (defun load-lits (clause new-clause)
  719.     (let
  720.         (
  721.             (first (first-lit clause))
  722.             (rest (remove-first-lit clause))
  723.             (negative nil)
  724.         )
  725.         (setq negative (lit-negative first))
  726.         (cond
  727.             ((null clause) new-clause)
  728.             ((member first new-clause :test #'equal)
  729.                 (load-lits rest new-clause)
  730.             )
  731.             ((member negative new-clause :test #'equal)
  732.                 (load-lits rest (remove negative new-clause :test #'equal))
  733.             )
  734.             (t (load-lits rest (append new-clause (list first))))
  735.         )
  736.     )
  737. )
  738. ;-------------------------------------------------------------------
  739. ;
  740. ;   Make substitutions from substitution list
  741. ;
  742. (defun make-subs (subs clause)
  743.     (let
  744.         (
  745.             (pair nil)
  746.         )
  747.         (cond
  748.             ((null clause) nil)
  749.             ((atom clause)
  750.                 (setq pair (assoc clause subs))
  751.                 (cond
  752.                     ((null pair) clause)
  753.                     (t (cadr pair))
  754.                 )
  755.             )
  756.             (t (mapcar `(lambda (x) (make-subs ',subs x)) clause))
  757.         )
  758.     )
  759. )
  760. ;-------------------------------------------------------------------
  761. ;
  762. ;   Add fact to the base hypotheses
  763. ;
  764. ;   Convert the fact to clause form.
  765. ;   If the result is a conjuction of clauses, set types and add them all;
  766. ;   else set the types and add the single clause.
  767. ;
  768. (defun assume (fact)
  769.     (setq fact (clause-convert fact))
  770.     (cond
  771.         ((equal (car fact) 'and)
  772.             (setq fact (mapcar 'set-types fact))
  773.             (setq base (append base (mapcar 'add-count (cdr fact))))
  774.         )
  775.         (t
  776.             (setq fact (set-types fact))
  777.             (setq base (append base (list (add-count fact))))
  778.         )
  779.     )
  780.     fact
  781. )
  782. ;-------------------------------------------------------------------
  783. ;
  784. ;   Return clause in a list preceded by the clause's literal-count
  785. ;
  786. (defun add-count (clause)
  787.     (list (literal-count clause) clause)
  788. )
  789. ;-------------------------------------------------------------------
  790. ;
  791. ;   Add a clause to the set-of-support -
  792. ;       add (clause X base) to pairs;
  793. ;       add clause to base
  794. ;
  795. (defun add-sos (clause)
  796.     (let
  797.         (
  798.             (pair (list (literal-count clause) clause))
  799.         )
  800.         (mapcar `(lambda (a) (add-pair pair a)) base)
  801.         (setq base (append base (list (add-count clause))))
  802.     )
  803. )
  804. ;-------------------------------------------------------------------
  805. ;
  806. ;   Insert a pair of clauses into pairs - returns pairs
  807. ;
  808. (defun add-pair (q b)
  809.     (let
  810.         (
  811.             (size-q (car q))
  812.             (size-b (car b))
  813.             (q-cl (cadr q))
  814.             (b-cl (cadr b))
  815.             (size 0)
  816.             (new-pair nil)
  817.         )
  818.         (cond
  819.             ((< size-q size-b)
  820.                 (setq size (+ (* 1000 size-q) size-b))
  821.                 (setq pairs (insert-pair (list size q-cl b-cl) pairs))
  822.             )
  823.             (t
  824.                 (setq size (+ (* 1000 size-b) size-q))
  825.                 (setq pairs (insert-pair (list size b-cl q-cl) pairs))
  826.             )
  827.         )
  828.     )
  829. )
  830. ;-------------------------------------------------------------------
  831. ;
  832. ;   Insert pair into pairs list - return new list
  833. ;
  834. (defun insert-pair (pair pair-list)
  835.     (cond
  836.         ((null pair-list) (list pair))
  837.  
  838.         ;  Use <= for "depth-first", < for "breadth-first"
  839.         ((< (car pair) (caar pair-list)) (cons pair pair-list))
  840.         (t (cons (car pair-list) (insert-pair pair (cdr pair-list))))
  841.     )
  842. )
  843. ;-------------------------------------------------------------------
  844. ;
  845. ;   Count the literals in a clause
  846. ;       Ignore a success clause and change 2's to 1 [e.g. (OR (A)) --> (A)]
  847. ;
  848. (defun literal-count (clause)
  849.     (setq clause (remove-success clause))
  850.     (cond
  851.         ((atom clause) 0)
  852.         ((literal-p clause) 1)
  853.         (t (1- (length clause)))
  854.     )
  855. )
  856. ;-------------------------------------------------------------------
  857. ;
  858. ;   Return the clause with any $success$ element removed
  859. ;
  860. (defun remove-success (clause)
  861.     (cond
  862.         ((atom clause) clause)
  863.         (t (remove nil (remove '$success$ clause :test #'deep-member)))
  864.     )
  865. )
  866. ;-------------------------------------------------------------------
  867. ;
  868. ;   Set the types for each name in the new line
  869. ;
  870. ;   Uses the global association list new-names
  871. ;
  872. ;   If a clause is nil, return nil.
  873. ;   If it's an atom, type it as variable or constant with separate routine.
  874. ;   If it's a list, pass the set-types through on mapcar.
  875. ;
  876. (defun set-types (clause)
  877.     (setq new-names nil)
  878.     (set-types* clause)
  879. )
  880. (defun set-types* (clause)
  881.     (cond
  882.         ((null clause) nil)
  883.         ((equal clause 'not) clause)
  884.         ((equal clause 'or) clause)
  885.         ((equal clause 'and) clause)
  886.         ((atom clause) (set-unit-type clause))
  887.         (t (mapcar 'set-types* clause))
  888.     )
  889. )
  890. ;
  891. ;-------------------------------------------------------------------
  892. ;
  893. ;   Set the type for an atom - either constant or variable
  894. ;
  895. ;   For constants:
  896. ;       Add name to names if new.
  897. ;
  898. ;   For variables:
  899. ;       Is the name is already in the new-names list?
  900. ;       Yes : return the associated name.
  901. ;       No  : Is the name in names?
  902. ;             Yes : Find an alternate name, add the substitution pair to
  903. ;                   new-names, add the new name to names with type variable
  904. ;                   and return the new name.
  905. ;             No  : Add the name to names with type variable, add an identity
  906. ;                   pair to new-names, return the original.
  907. ;
  908. (defun set-unit-type (atm)
  909.     (let
  910.         (
  911.             (g-symb atm)        ; Substitution name
  912.             (atm-type 'variable)
  913.             (pair nil)
  914.         )
  915.         (cond
  916.             ((equal (get atm 'type) 'constant) nil)
  917.             ((char> (char (symbol-name atm) 0) #\F)
  918.  
  919.                 ; If first character > F, it's a variable.
  920.                 (setq pair (assoc atm new-names))
  921.                 (cond
  922.                     ((not (null pair)) (setq g-symb (cadr pair)))
  923.                     (t
  924.                         (cond
  925.                             ((member atm names)
  926.                                 (setq g-symb (gensym))
  927.                                 (add-new-name atm g-symb)
  928.                             )
  929.                             (t  (add-new-name atm atm))
  930.                         )
  931.                     )
  932.                 )
  933.             )
  934.         )
  935.         (add-name g-symb)
  936.     )
  937. )
  938. ;
  939. ;-------------------------------------------------------------------
  940. ;
  941. ;   If the atom is not found in names, add it with given type.
  942. ;   Return the atom
  943. ;
  944. (defun add-name (atm)
  945.     (cond
  946.         ((member atm names) atm)
  947.         (t (setq names (cons atm names)))
  948.     )
  949.     (cond
  950.         ((get atm 'type) nil)
  951.         ((char<= (char (symbol-name atm) 0) #\F) (putprop atm 'constant 'type))
  952.         (t (putprop atm 'variable 'type))
  953.     )
  954.     atm
  955. )
  956. ;
  957. ;-------------------------------------------------------------------
  958. ;
  959. ;   Add a new name to the new-names a-list.  Return the substitution
  960. ;   value
  961. ;
  962. (defun add-new-name (x y)
  963.     (setq new-names (cons (list x y) new-names))
  964.     y
  965. )
  966. ;-------------------------------------------------------------------
  967. ;
  968. ;   Find x at any depth in list
  969. ;
  970. (defun deep-member (x lst)
  971.     (cond
  972.         ((equal x lst) t)
  973.         ((atom lst) nil)
  974.         ((deep-member x (car lst)) t)
  975.         (t (deep-member* x (cdr lst)))
  976.     )
  977. )
  978. (defun deep-member* (x lst)     ; To avoid x = cdr
  979.     (cond
  980.         ((null lst) nil)
  981.         ((deep-member x (car lst)) t)
  982.         (t (deep-member* x (cdr lst)))
  983.     )
  984. )
  985. ;-------------------------------------------------------------------
  986. ;
  987. ;   Print prompt and get input
  988. ;
  989. (defun get-input (mode)
  990.     (terpri)
  991.     (cond
  992.         ((equal mode 'assert) (princ "Assert --"))
  993.         (t (princ "Question --"))
  994.     )
  995.     (read)
  996. )
  997. ;
  998. ;-------------------------------------------------------------------
  999. ;
  1000. ;   Test if x is a literal
  1001. ;
  1002. (defun literal-p (x)
  1003.     (cond
  1004.         ((atom x) nil)
  1005.         ((equal (car x) 'not)
  1006.             (not (member (caadr x) (cons 'not operators)))
  1007.         )
  1008.         ((member (car x) operators) nil)
  1009.         (t t)
  1010.     )
  1011. )
  1012. ;-------------------------------------------------------------------
  1013. ;
  1014. ;   Find first literal in x
  1015. ;
  1016. (defun first-lit (x)
  1017.     (cond
  1018.         ((atom x) nil)
  1019.         ((equal (car x) 'or) (cadr x))
  1020.         (t x)
  1021.     )
  1022. )
  1023. ;-------------------------------------------------------------------
  1024. ;
  1025. ;   Return x with first literal removed (keep OR unless down to one literal
  1026. ;
  1027. (defun remove-first-lit (x)
  1028.     (cond
  1029.         ((atom x) nil)
  1030.         ((literal-p x) nil)       ; If not, must be clause
  1031.         ((equal (car x) '$success$) nil)
  1032.         ((<= (length x) 3) (car (cdr (cdr x))))
  1033.         (t (cons 'or (cdr (cdr x))))
  1034.     )
  1035. )
  1036. ;-------------------------------------------------------------------
  1037. ;
  1038. ;   Count the items in a list - for memory test purposes
  1039. ;
  1040. (defun deep-count (x)
  1041.     (cond
  1042.         ((null x) 0)
  1043.         ((atom x) 1)
  1044.         (t
  1045.             (apply '+ (mapcar 'deep-count x))
  1046.         )
  1047.     )
  1048. )
  1049. ;-------------------------------------------------------------------
  1050. ;
  1051. ;   Set global variables to initial states
  1052. ;
  1053. (defun init-qa ()
  1054.     (setq base nil)
  1055.     (setq names '(not or))
  1056.     (setq show-proof t)
  1057.     (setq show-unify nil)
  1058.     (setq show-pairs nil)
  1059.     (setq max-pairs 400)
  1060.     (putprop 'not       'constant 'type)
  1061.     (putprop 'or        'constant 'type)
  1062.     (putprop '$success$ 'constant 'type)
  1063.     (putprop 'and       'constant 'type)
  1064.     (putprop 'imply     'constant 'type)
  1065.     (putprop 'equiv     'constant 'type)
  1066.     (setq operators '(or and imply equiv))    ; Can't begin a literal
  1067.     (setq mode 'assert)
  1068.     (setq in-line 0)
  1069.     (princ "Type HELP for help.\n\n")
  1070. )
  1071. ;
  1072. ;-------------------------------------------------------------------
  1073. ;
  1074. ;   CLAUSE CONVERSION CODE
  1075. ;
  1076. ;   Convert the fact to clause form
  1077. ;
  1078. (defun clause-convert (fact)
  1079.     (let
  1080.         (
  1081.             (result fact)
  1082.         )
  1083.         (cond
  1084.             ((atom fact) fact)
  1085.             ((literal-p fact) fact)
  1086.             (t
  1087.                 (setq result (cc-equiv result))
  1088.                 (setq result (cc-imply result))
  1089.                 (setq result (cc-push-not result))
  1090.                 (setq result (cc-push-or result))
  1091.                 (setq result (cc-disassoc result))
  1092.                 result
  1093.             )
  1094.         )
  1095.     )
  1096. )
  1097. ;-------------------------------------------------------------------
  1098. ;
  1099. ;   Convert clause form (equiv (a) (b)) -->
  1100. ;           (and (imply (a) (b)) (imply (b) (a)))
  1101. ;
  1102. ;
  1103. (defun cc-equiv (c)
  1104.     (cond
  1105.         ((atom c) c)
  1106.         ((literal-p c) c)
  1107.         ((equal (car c) 'equiv)
  1108.             `(and
  1109.                 (imply ,(cc-equiv (cadr c)) ,(cc-equiv (caddr c)))
  1110.                 (imply ,(cc-equiv (caddr c)) ,(cc-equiv (cadr c)))
  1111.             )
  1112.         )
  1113.         (t (mapcar 'cc-equiv c))
  1114.     )
  1115. )
  1116. ;-------------------------------------------------------------------
  1117. ;
  1118. ;   Convert clause form (imply (a) (b)) -->
  1119. ;       (or (not (a)) (b))
  1120. ;
  1121. ;
  1122. (defun cc-imply (c)
  1123.     (cond
  1124.         ((atom c) c)
  1125.         ((literal-p c) c)
  1126.         ((equal (car c) 'imply)
  1127.             `(or
  1128.                 (not ,(cc-imply (cadr c)))
  1129.                 ,(cc-imply (caddr c))
  1130.             )
  1131.         )
  1132.         (t (mapcar 'cc-imply c))
  1133.     )
  1134. )
  1135. ;-------------------------------------------------------------------
  1136. ;
  1137. ;   Push NOTs down to literals -
  1138. ;       (not (not (a))) --> (a)
  1139. ;       (not (or (a) (b) (c))) --> (and (not (a)) (not (b)) (not (c)))
  1140. ;       (not (and (a) (b) (c))) --> (or (not (a)) (not (b)) (not (c)))
  1141. ;       (not (exist x (...)) --> (all x (not (...)))
  1142. ;       (not (all x (...)) --> (exist x (not (...)))
  1143. ;
  1144. ;
  1145. (defun cc-push-not (c)              ; No prior NOT being pushed
  1146.     (cond
  1147.         ((atom c) c)
  1148.         ((literal-p c) c)
  1149.         ((equal (car c) 'not) (cc-push-not* (cadr c)))
  1150.         (t (mapcar 'cc-push-not c))
  1151.     )
  1152. )
  1153. (defun cc-push-not* (c)             ; Prior NOT being pushed
  1154.     (cond
  1155.         ((atom c) c)
  1156.         ((literal-p c) (lit-negative c))
  1157.         ((equal (car c) 'not) (cc-push-not (cadr c)))
  1158.         ((equal (car c) 'and)
  1159.             (append '(or) (mapcar 'cc-push-not* (cdr c)))
  1160.         )
  1161.         ((equal (car c) 'or)
  1162.             (append '(and) (mapcar 'cc-push-not* (cdr c)))
  1163.         )
  1164.         ((equal (car c) 'exist)
  1165.             (append `(all ,(cadr c)) (mapcar 'cc-push-not* (caddr c)))
  1166.         )
  1167.         ((equal (car c) 'all)
  1168.             (append `(exist ,(cadr c)) (mapcar 'cc-push-not* (caddr c)))
  1169.         )
  1170.     )
  1171. )
  1172. ;----------------------------------------------------------------------
  1173. ;
  1174. ;   Move all the ORs down below the AND's
  1175. ;
  1176. ;
  1177. (defun cc-push-or (c)
  1178.     (cond
  1179.         ((atom c) c)
  1180.         ((literal-p c) c)
  1181.         ((equal (length c) 2) (cadr c))     ; (AND/OR (a)) --> (a)
  1182.  
  1183.         ((equal (car c) 'or)
  1184.             (cc-or-merge
  1185.                 (cc-push-or (cadr c))
  1186.                 (cc-push-or (append '(or) (cddr c)))
  1187.             )
  1188.         )
  1189.         (t (mapcar 'cc-push-or c))
  1190.     )
  1191. )
  1192. ;----------------------------------------------------------------------
  1193. ;
  1194. ;   Merge two cleaned-up forms with an OR
  1195. ;
  1196. ;
  1197. (defun cc-or-merge (x y)
  1198.     (cond
  1199.         ((null x) y)
  1200.         ((null y) (cc-or-merge y x))
  1201.         ((atom x)
  1202.             (princ "Error in cc-or-merge - invalid form ")
  1203.             (print x)
  1204.         )
  1205.         ((atom y) (cc-or-merge y x))
  1206.         ((equal (car x) 'and)
  1207.             (append
  1208.                 '(and)
  1209.                 (mapcar '(lambda (a) (cc-or-merge y a)) (cdr x))
  1210.             )
  1211.         )
  1212.         ((equal (car y) 'and) (cc-or-merge y x))
  1213.         (t `(or ,x ,y))
  1214.     )
  1215. )
  1216. ;----------------------------------------------------------------------
  1217. ;
  1218. ;   Flatten the form by the association rule
  1219. ;
  1220. ;
  1221. (defun cc-disassoc (c)
  1222.     (cond
  1223.         ((atom c) c)
  1224.         ((literal-p c) c)
  1225.  
  1226.         ; (AND/OR (a)) --> (a)
  1227.         ((equal (length c) 2) (cc-disassoc (cadr c)))
  1228.  
  1229.         (t
  1230.             (cc-merge-assoc
  1231.                 (car c)
  1232.                 (cc-disassoc (cadr c))
  1233.                 (cc-disassoc (caddr c))
  1234.             )
  1235.         )
  1236.     )
  1237. )
  1238. ;----------------------------------------------------------------------
  1239. ;
  1240. ;   Merge two cleaned-up forms by association
  1241. ;
  1242. ;
  1243. (defun cc-merge-assoc (op x y)
  1244.     (cond
  1245.         ((null x) y)
  1246.         ((null y) (cc-merge-assoc op y x))
  1247.         ((atom x)
  1248.             (princ "Error in cc-merge-assoc - invalid form ")
  1249.             (print x)
  1250.         )
  1251.         ((atom y) (cc-merge-assoc op y x))
  1252.  
  1253.         (t
  1254.             (append
  1255.                 (list op)
  1256.                 (cond
  1257.                     ((equal (car x) op) (cdr x))
  1258.                     (t (list x))
  1259.                 )
  1260.                 (cond
  1261.                     ((equal (car y) op) (cdr y))
  1262.                     (t (list y))
  1263.                 )
  1264.             )
  1265.         )
  1266.         ((equal (car y) 'and) (cc-merge-assoc y x))
  1267.         (t `(or ,x ,y))
  1268.     )
  1269. )
  1270.  
  1271. (qa)
  1272.