// -*- Mode: LISP; Syntax: Common-lisp; Package: DTP; Base: 10 -*- // ---------------------------------------------------------------------------- // // File Literals.Lisp // System Don's Theorem Prover // // Written by Don Geddis (Geddis@CS.Stanford.Edu) "(in-package dtp)"; // ---------------------------------------------------------------------------- // // Data Structures // A literal define class () slot literal-negated-p, init-keyword: #"literal-negated-p"; slot literal-relation, init-keyword: #"literal-relation"; slot literal-terms, init-keyword: #"literal-terms"; end class ; // ---------------------------------------------------------------------------- define method literal-node-print-function (structure, stream, depth) format(stream, "<"); print-literal-node(structure, s: stream); format(stream, ">"); end method literal-node-print-function; define method print-literal-node (node, #key s = #t, flip-negation = #f) if (*display-logic-as-lists*) print-literal-node-as-list(node, s: s, flip-negation: flip-negation); else print-literal-node-as-logic(node, s: s, flip-negation: flip-negation); end if; end method print-literal-node; define method print-literal-node-as-list (node, #key s = #t, flip-negation = #f) if (~ (node.literal-negated-p == flip-negation)) format(s, "(not "); end if; format(s, "("); (method (s, #rest args) apply(maybe-initiate-xp-printing, method (xp, #rest args) begin push-char-mode(xp, #"cap1"); fluid-bind (*print-escape* = #f) write+(pop!(args), xp); end fluid-bind; pop-char-mode(xp); end; if (args) copy-sequence(args); end if; end method, s, args); end method)(s, node.literal-relation); if (node.literal-terms) (method (s, #rest args) apply(maybe-initiate-xp-printing, method (xp, #rest args) let args = pop!(args); block (return) local method go-l () if (empty?(args)) return(#f); end if; write-char++(' ', xp); fluid-bind (*print-escape* = #t) write+(pop!(args), xp); end fluid-bind; go-l(); end method go-l; go-l(); end block; if (args) copy-sequence(args); end if; end method, s, args); end method)(s, node.literal-terms); end if; format(s, ")"); if (~ (node.literal-negated-p == flip-negation)) format(s, ")"); end if; end method print-literal-node-as-list; define method print-literal-node-as-logic (node, #key s = #t, flip-negation = #f) if (~ (node.literal-negated-p == flip-negation)) format(s, "~"); end if; (method (s, #rest args) apply(maybe-initiate-xp-printing, method (xp, #rest args) begin push-char-mode(xp, #"cap1"); fluid-bind (*print-escape* = #f) write+(pop!(args), xp); end fluid-bind; pop-char-mode(xp); end; if (args) copy-sequence(args); end if; end method, s, args); end method)(s, node.literal-relation); if (node.literal-terms) let term-strings = #f; term-strings := map(method (term) let s = // LTD: Function MAKE-STRING-OUTPUT-STREAM not yet implemented. make-string-output-stream(element-type: #f); block (nil) begin term-to-string(term, s); end; cleanup close(s); end block; // LTD: Function GET-OUTPUT-STREAM-STRING not yet implemented. get-output-stream-string(s); end method, node.literal-terms); (method (s, #rest args) apply(maybe-initiate-xp-printing, method (xp, #rest args) begin write-char++('(', xp); fluid-bind (*print-escape* = #f) write+(pop!(args), xp); end fluid-bind; let args = pop!(args); block (return) local method go-l () if (empty?(args)) return(#f); end if; write-char++(',', xp); fluid-bind (*print-escape* = #f) write+(pop!(args), xp); end fluid-bind; go-l(); end method go-l; go-l(); end block; write-char++(')', xp); end; if (args) copy-sequence(args); end if; end method, s, args); end method)(s, head(term-strings), tail(term-strings)); end if; end method print-literal-node-as-logic; define method term-to-string (term, #key s = #t) // Variable terms -> lowercase string, Constant terms -> capitalized string if (varp(term)) (method (s, #rest args) apply(maybe-initiate-xp-printing, method (xp, #rest args) begin push-char-mode(xp, #"down"); fluid-bind (*print-escape* = #f) write+(pop!(args), xp); end fluid-bind; pop-char-mode(xp); end; if (args) copy-sequence(args); end if; end method, s, args); end method)(s, variable-to-string(term)); elseif (instance?(term, )) (method (s, #rest args) apply(maybe-initiate-xp-printing, method (xp, #rest args) begin push-char-mode(xp, #"cap1"); fluid-bind (*print-escape* = #f) write+(pop!(args), xp); end fluid-bind; pop-char-mode(xp); end; if (args) copy-sequence(args); end if; end method, s, args); end method)(s, first(term)); if (tail(term)) format(s, "("); end if; format(s, "%S", begin let str = // LTD: Function MAKE-STRING-OUTPUT-STREAM not yet implemented. make-string-output-stream(element-type: #f); block (nil) begin for (remaining-terms = tail(term) then tail(remaining-terms), until empty?(remaining-terms), subterm = first(remaining-terms) then first(remaining-terms)) term-to-string(subterm, str); if (tail(remaining-terms)) format(str, ","); end if; end for; end; cleanup close(str); end block; // LTD: Function GET-OUTPUT-STREAM-STRING not yet implemented. get-output-stream-string(str); end); if (tail(term)) format(s, ")"); end if; elseif (instance?(term, )) format(s, "%=", term); else (method (s, #rest args) apply(maybe-initiate-xp-printing, method (xp, #rest args) begin push-char-mode(xp, #"cap1"); fluid-bind (*print-escape* = #f) write+(pop!(args), xp); end fluid-bind; pop-char-mode(xp); end; if (args) copy-sequence(args); end if; end method, s, args); end method)(s, term); end if; end method term-to-string; // ---------------------------------------------------------------------------- define method list-to-literal (list, #key replacement-bindings = #f) let lit = make-literal-node(); if (#"not" == first(list)) lit.literal-negated-p := #t; list := second(list); end if; lit.literal-relation := first(list); if (replacement-bindings) lit.literal-terms := plug(tail(list), replacement-bindings); else lit.literal-terms := tail(list); end if; lit; end method list-to-literal; // ---------------------------------------------------------------------------- define method literal-to-list (literal, #key ignore-negation = #f) let new-list = pair(literal.literal-relation, literal.literal-terms); if (~ ignore-negation) if (literal.literal-negated-p) new-list := list(#"not", new-list); end if; end if; new-list; end method literal-to-list; // ---------------------------------------------------------------------------- define method literal-list-equal-p (literal, list, #key test = \=) // True iff the literal is equivalent to the list representation let list-negation = first(list) == #"not"; if (list-negation) list := second(list); end if; literal.literal-negated-p == list-negation & literal.literal-relation == first(list) & test(literal.literal-terms, tail(list)); end method literal-list-equal-p; // ---------------------------------------------------------------------------- define method literal-plug (literal, binding-list) // Return a new literal, which is a copy of LITERAL with BINDING-LIST applied let copy = copy-literal-node(literal); copy.literal-terms := plug(copy.literal-terms, binding-list); copy; end method literal-plug; define method nliteral-plug (literal, binding-list) // Destructively modify LITERAL by applying BINDING-LIST literal.literal-terms := plug(literal.literal-terms, binding-list); literal; end method nliteral-plug; // ---------------------------------------------------------------------------- define method literal-flip-negation (literal) // Return a copy of LITERAL with opposite sign let copy = copy-literal-node(literal); copy.literal-negated-p := ~ copy.literal-negated-p; copy; end method literal-flip-negation; define method nliteral-flip-negation (literal) // Destructively modify LITERAL to have opposite sign literal.literal-negated-p := ~ literal.literal-negated-p; literal; end method nliteral-flip-negation; // ---------------------------------------------------------------------------- define method query-to-answer-literal (query) make-literal-node(relation: #"answer_", terms: find-vars(query)); end method query-to-answer-literal; // ---------------------------------------------------------------------------- define method nliteral-rename-all-variables (literal) let bl = literal-rename-binding-list(literal); nliteral-plug(literal, bl); end method nliteral-rename-all-variables; define method literal-rename-binding-list (literal) map(method (x) pair(x, make-new-variable(x)); end method, cl-remove-duplicates(find-vars(literal.literal-terms))); end method literal-rename-binding-list; // ---------------------------------------------------------------------------- define method literal-vars-in (literal) // Returns list (set) of variables in terms of literal cl-remove-duplicates(find-vars(literal.literal-terms)); end method literal-vars-in; // ---------------------------------------------------------------------------- define method function-depth (literal) // The maximum depth of function application to any term in LITERAL if (literal.literal-terms) tree-depth(literal.literal-terms) - 1; else 0; end if; end method function-depth; // ---------------------------------------------------------------------------- // // Literal equality tests // ---------------------------------------------------------------------------- define method literal-possible-negated-pair-p (lit1, lit2) // Negated pair, but knows about EVAL ~ (lit1.literal-negated-p == lit2.literal-negated-p) & lit1.literal-relation == lit2.literal-relation & dtp-unifyp(map(eval-to-var, lit1.literal-terms), map(eval-to-var, lit2.literal-terms)); end method literal-possible-negated-pair-p; define method eval-to-var (term) if (instance?(term, ) & first(term) == #"eval") make-new-variable(#"?eval"); else term; end if; end method eval-to-var; // ---------------------------------------------------------------------------- define method literal-negated-pair-p (lit1, lit2, #key test = dtp-unifyp) // Returns unifying binding list, if negated pair, else nil lit1 & lit2 & ~ (lit1.literal-negated-p == lit2.literal-negated-p) & lit1.literal-relation == lit2.literal-relation & test(lit1.literal-terms, lit2.literal-terms); end method literal-negated-pair-p; // ---------------------------------------------------------------------------- define method literal-mgu (lit1, lit2, #key ignore-sign = #f) // Returns most general unifier of terms of both literals, if exists, else nil if (ignore-sign | lit1.literal-negated-p == lit2.literal-negated-p & lit1.literal-relation == lit2.literal-relation) dtp-unifyp(lit1.literal-terms, lit2.literal-terms); end if; end method literal-mgu; // ---------------------------------------------------------------------------- define method literal-instance (general-literal, instance-literal, #key old-binding-list = #f) // True iff INSTANCE-LITERAL is an instance of GENERAL-LITERAL general-literal.literal-negated-p == instance-literal.literal-negated-p & general-literal.literal-relation == instance-literal.literal-relation & dtp-instp(general-literal.literal-terms, instance-literal.literal-terms, old-binding-list); end method literal-instance; // ---------------------------------------------------------------------------- define method literal-instance? (instance, general) // True IFF INSTANCE is more specific (or equal) to GENERAL literal-instance(general, instance); end method literal-instance?; // ---------------------------------------------------------------------------- define method literal-same-or-generalized-p (instance-literal, general-literal) // True iff I-LITERAL is same as or an instance of G-LITERAL instance-literal.literal-negated-p == general-literal.literal-negated-p & instance-literal.literal-relation == general-literal.literal-relation & dtp-instp(general-literal.literal-terms, instance-literal.literal-terms); end method literal-same-or-generalized-p; // ---------------------------------------------------------------------------- define method literal-equal-p (lit1, lit2) lit1.literal-negated-p == lit2.literal-negated-p & lit1.literal-relation == lit2.literal-relation & lit1.literal-terms = lit2.literal-terms; end method literal-equal-p; // ---------------------------------------------------------------------------- define method literal-samep (lit1, lit2) lit1.literal-negated-p == lit2.literal-negated-p & lit1.literal-relation == lit2.literal-relation & samep(lit1.literal-terms, lit2.literal-terms); end method literal-samep; // ---------------------------------------------------------------------------- "eof";