1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182
|
(in-package "ACL2")
(set-state-ok t)
;; This clause processor lets one replace one of the hyps (i.e. the negation of
;; one of the literals of the clause) with something that hyp provably
;; implies. See the comment above (defun replace-impl ... ) below.
(defevaluator use-impl-ev use-impl-ev-list
((not x) (if a b c) (implies a b)))
(defthm conjoin-clauses-of-one
(equal (conjoin-clauses (list x))
(disjoin x)))
(defthm use-impl-ev-conjoin-clauses-of-two-or-more
(iff (use-impl-ev (conjoin-clauses (cons x (cons y z))) a)
(and (use-impl-ev (disjoin x) a)
(use-impl-ev (conjoin-clauses (cons y z)) a))))
(in-theory (disable conjoin-clauses))
(defthm use-impl-ev-of-disjoin1
(iff (use-impl-ev (disjoin (cons x y)) a)
(or (use-impl-ev x a)
(use-impl-ev (disjoin y) a))))
(defthm use-impl-ev-of-conjoin1
(iff (use-impl-ev (conjoin (cons x y)) a)
(and (use-impl-ev x a)
(use-impl-ev (conjoin y) a))))
(defthm use-impl-ev-of-disjoin2
(implies (not (consp x))
(equal (use-impl-ev (disjoin x) a) nil)))
(defthm use-impl-ev-of-conjoin2
(implies (not (consp x))
(equal (use-impl-ev (conjoin x) a) t)))
(defthm pseudo-term-listp-cons
(iff (pseudo-term-listp (cons x y))
(and (pseudo-termp x)
(pseudo-term-listp y))))
(in-theory (disable conjoin disjoin pseudo-term-listp))
(defun replace-impl-fn (hyp sense repl clause)
(declare (xargs :guard t))
(if (atom clause)
(mv t clause)
(let ((lit (car clause)))
(if sense
(if (equal lit hyp)
(mv nil (cons (list 'not repl) (cdr clause)))
(mv-let (samep rest)
(replace-impl-fn hyp sense repl (cdr clause))
(if samep
(mv t clause)
(mv nil (cons (car clause) rest)))))
(if (and (consp lit)
(eq (car lit) 'not)
(consp (cdr lit))
(equal (cadr lit) hyp))
(mv nil (cons (list 'not repl) (cdr clause)))
(mv-let (samep rest)
(replace-impl-fn hyp sense repl (cdr clause))
(if samep
(mv t clause)
(mv nil (cons (car clause) rest)))))))))
(defthm replace-impl-fn-same
(implies (mv-nth 0 (replace-impl-fn hyp sense repl clause))
(equal (mv-nth 1 (replace-impl-fn hyp sense repl clause))
clause)))
(defthm replace-impl-fn-correct
(implies (and (use-impl-ev (disjoin (mv-nth 1 (replace-impl-fn
hyp sense repl clause))) a)
(or (if sense
(use-impl-ev hyp a)
(not (use-impl-ev hyp a)))
(use-impl-ev repl a)))
(use-impl-ev (disjoin clause) a))
:rule-classes :forward-chaining)
(defun replace-impl-cp (clause term)
(declare (xargs :guard t))
(if (eql (len term) 2)
(let ((hyp (car term))
(repl (cadr term)))
(mv-let (samep cl)
(if (and (consp hyp) (eq (car hyp) 'not) (consp (cdr hyp)))
(replace-impl-fn (cadr hyp) t repl clause)
(replace-impl-fn hyp nil repl clause))
(if samep
(list clause)
(list cl (list `(not ,hyp) repl)))))
(list clause)))
(defthm replace-impl-cp-correct
(implies (and (pseudo-term-listp cl)
(alistp a)
(use-impl-ev (conjoin-clauses
(replace-impl-cp cl term))
a))
(use-impl-ev (disjoin cl) a))
:rule-classes :clause-processor)
(mutual-recursion
(defun term-sublis (al x)
(declare (xargs :guard (and (alistp al)
(pseudo-termp x))
:mode :program))
(cond ((atom x)
(let ((entry (assoc x al)))
(if entry (cdr entry) x)))
((eq (car x) 'quote) x)
(t
;; Don't dive into lambdas, but do term-sublis the args.
(cons (car x) (term-list-sublis al (cdr x))))))
(defun term-list-sublis (al x)
(declare (xargs :guard (and (alistp al)
(pseudo-term-listp x))))
(if (atom x)
nil
(cons (term-sublis al (car x))
(term-list-sublis al (cdr x))))))
(defun find-instance-fn (x sense cl)
(declare (xargs :mode :program))
(if (atom cl)
(mv nil nil nil)
(if sense
(mv-let (okp al)
(one-way-unify x (car cl))
(if okp
(mv okp (list 'not (car cl)) al)
(find-instance-fn x sense (cdr cl))))
(if (and (consp (car cl))
(eq (car (car cl)) 'not))
(mv-let (okp al)
(one-way-unify x (cadr (car cl)))
(if okp
(mv okp (cadr (car cl)) al)
(find-instance-fn x sense (cdr cl))))
(find-instance-fn x sense (cdr cl))))))
(defun find-instance (hyp-pat concl-pat cl)
(declare (xargs :mode :program))
(mv-let (ok hyp alst)
(if (and (consp hyp-pat)
(eq (car hyp-pat) 'not))
(find-instance-fn (cadr hyp-pat) t cl)
(find-instance-fn hyp-pat nil cl))
(mv ok hyp (and ok (term-sublis alst concl-pat)))))
;; This is a computed hint which searches cl for a negated literal HYP that
;; unifies with (the translated version of) hyp-pat. It then replaces this
;; literal with the result CONCL of substituting the variables of concl-pat for
;; the ones that matched in hyp-pat. It is then also necessary to prove that
;; HYP implies CONCL.
(defun replace-impl (hyp-pat concl-pat cl state)
(declare (xargs :mode :program))
(er-let* ((hyp-pat (translate hyp-pat t t t 'replace-impl (w state) state))
(concl-pat (translate concl-pat t t t 'replace-impl (w state) state)))
(mv-let (ok hyp concl)
(find-instance hyp-pat concl-pat cl)
(value
(and ok
`(:clause-processor (replace-impl-cp clause
',(list hyp concl))))))))
|