diff options
Diffstat (limited to 'books/workshops/2004/ruiz-et-al/support/terms-as-dag.lisp')
-rw-r--r-- | books/workshops/2004/ruiz-et-al/support/terms-as-dag.lisp | 3223 |
1 files changed, 3223 insertions, 0 deletions
diff --git a/books/workshops/2004/ruiz-et-al/support/terms-as-dag.lisp b/books/workshops/2004/ruiz-et-al/support/terms-as-dag.lisp new file mode 100644 index 0000000..705a4f2 --- /dev/null +++ b/books/workshops/2004/ruiz-et-al/support/terms-as-dag.lisp @@ -0,0 +1,3223 @@ +;;; ============================================================================ +;;; terms-as-dag.lisp +;;; Título: Storing first--order terms as dags +;;; ============================================================================ + +#| To certify this book: + +(in-package "ACL2") + +(certify-book "terms-as-dag") + + +|# + +(in-package "ACL2") + + +(include-book "dag-unification-rules") + + +;;; ============================================================================ +;;; +;;; 0) Introducción +;;; +;;; ============================================================================ + +;;; In this book ({\tt terms-as-dag.lisp}), we define a function to +;;; store first--order terms (respresented in standard list/prefix +;;; notation) as directed acyclic graphs (dags), with shared +;;; variables. This function is essential (it is the first step) in the +;;; design of a unification algorithm using a dag representation. + +;;; The following function {\tt term-as-dag} (with its main auxiliary +;;; function {\tt term-as-dag-aux}) receives as input a first--order +;;; term and a graph and returns a graph that stores the input terms +;;; (following the conventions explained in the book {\tt +;;; dags.lisp}). Note that the result is a graph such that the term +;;; pointed by the index @0@ is the input term: + + + +(defun term-as-dag-aux (flg term g h variables) + (if flg + (if (variable-p term) + (let* ((bound (assoc term variables)) + (g (update-dagi-l h (if bound (cdr bound) (cons term t)) g)) + (new-variables (if bound variables (acons term h variables)))) + (mv g (1+ h) nil new-variables)) + (mv-let (g h1 hsl var1) + (term-as-dag-aux nil (cdr term) g (1+ h) variables) + (let* ((g (update-dagi-l h (cons (car term) hsl) g))) + (mv g h1 nil var1)))) + (if (endp term) + (mv g h term variables) + (mv-let (g hcar ign varcar) + (term-as-dag-aux t (car term) g h variables) + (declare (ignore ign)) + (mv-let (g hcdr hsl varcdr) + (term-as-dag-aux nil (cdr term) g hcar varcar) + (mv g hcdr (cons h hsl) varcdr)))))) + +(defun term-as-dag (term g) + (mv-let (g h hs var) + (term-as-dag-aux t term g 0 nil) + (declare (ignore h hs var)) + g)) + +;;; Example: + +; ACL2 !>(term-as-dag +; '(f (h x) y (k (g (k y) (k x z)))) +; '(nil nil nil nil nil nil nil nil nil nil nil)) +; ((F 1 3 4) (H 2) (X . T) +; (Y . T) +; (K 5) (G 6 8) (K 7) 3 (K 9 10) 2 (Z . T)) + + +;;; The main auxiliary function {\tt term-as-dag-aux} is defined +;;; recursively in the structure of the term stored. The flag @flg@ +;;; indicates if @term@ is considered to be a term or a list of terms, +;;; as usual. The argument @h@ is an index in the graph @g@; from this index +;;; on, the term is going to be stored in the graph. Since the term is +;;; stored with shared variables, the argument @variables@ stored a +;;; association list, associating variables previously stored with the +;;; corresponding index of the node where the variable is already stored +;;; in the graph. + +;;; This function returns a multivalue with four values. The first one +;;; is the new graph obtained, the second is the first available index +;;; after the proccess, the third (only makes sense for the case of +;;; lists of terms) is the list of initial indices where each of the +;;; terms of the list have been stored, and the fourth is the new +;;; association list of variables to indices, extending the input +;;; association list. + +;;; Our goal in this book is to verify this function, showing that it +;;; sores a term in the conditions required by the rules of +;;; transformation of a unification algorithm acting on term dags (see +;;; {\tt dag\--unification\--rules\-.lisp}. That is, we prove the +;;; following theorems (the predicate {\tt empty-graph-p} describes +;;; graphs with @nil@ in all its positions): + +; (defthm term-as-dag-term-graph-p +; (implies (and (empty-graph-p g) (term-p term)) +; (term-graph-p (term-as-dag term g)))) + + + +; (defthm term-as-dag-dag-p +; (implies (and (empty-graph-p g) (term-p term)) +; (dag-p (term-as-dag term g)))) + + +; (defthm term-as-dag-stores-term +; (implies (and (empty-graph-p g) (term-p term)) +; (equal (dag-as-term t 0 (term-as-dag term g)) +; term))) + + +; (defthm term-as-dag-no-duplicatesp-variables +; (implies (and (empty-graph-p g) (term-p term)) +; (no-duplicatesp +; (list-of-term-dag-variables (term-as-dag term g)))) + + +;;; These theorems ensure that we can use the function @term-as-dag@ to +;;; store well--formed unification problems (see the book {\tt +;;; dag-unification-rules.lisp}). In fact, in the last section of this +;;; book, we define and verify a function that (using the above function +;;; {\tt term-as-dag}) stores a given unification problem as directed +;;; acyclicic graph. + +;;; Finally, note that for the moment we are not talking about +;;; single--threaded objects. But later (book {\tt +;;; dag-unification-st.lisp}), we will use the properties of +;;; these functions to verify an analogue functions defined using stobjs +;;; (that is, the graph obtained will be destructively updated). + + +;;; The following books are used, and contain information that is +;;; relevant to understand the contents of this book: + +;;; *) +;;; The book {\tt dag-unification-rules} describes the rules of +;;; transformation of unification, done with a dag representation of +;;; terms. It includes the book {\tt dags.lisp}, where it is described +;;; how term graphs are represented and the meaning of the information +;;; stored in the nodes +;;; -) + + +;;; ============================================================================ +;;; +;;; 1) The proof strategy +;;; +;;; ============================================================================ + +;;; Note that verifying the function @term-as-dag@ may be difficult, +;;; for several reasons: + +;;; *) +;;; We use an association list to avoid duplication of variables. +;;; *) +;;; The node corresponding to a function symbol is updated {\em after} +;;; the list of its arguments have been stored. +;;; *) +;;; To store a list of terms, the @cdr@ of the list is stored having +;;; as input the graph obtained after storing the @car@ of the list. +;;; *) +;;; We must ensure that the graph stored is a directed acyclic graph +;;; (as defined by @dag-p@). In particular this property has to be +;;; held in every stage of the proccess (because we need to use +;;; induction hypothesis in the proof of the theorems). +;;; -) + +;;; We tried to verify the functions directly and it turned (not very +;;; surprisingly) very difficult. So we explain now the approach we +;;; followed. The main idea is to employ some kind of compositional +;;; reasoning, in order to consider the difficult issues of the proofs +;;; separately. In particular, we reason about "shared variables" and +;;; the proccess of "storing the term", separately. + +;;; For that purpose, we define a version of {\tt term-as-dag-aux}, +;;; called {\tt term-as-dag-aux-ns}, storing terms (or list of terms) +;;; but without the burden of getting shared variables. Note that we do +;;; not need in this case the association list of variables to indices: + + +(local + (defun term-as-dag-aux-ns (flg term g h) + (if flg + (if (variable-p term) + (let ((g (update-dagi-l h (cons term t) g))) + (mv g (1+ h) nil)) + (mv-let (g h1 hsl) + (term-as-dag-aux-ns nil (cdr term) g (1+ h)) + (let* ((g (update-dagi-l h (cons (car term) hsl) g))) + (mv g h1 nil)))) + (if (endp term) + (mv g h term) + (mv-let (g hcar ign) + (term-as-dag-aux-ns t (car term) g h) + (declare (ignore ign)) + (mv-let (g hcdr hsl) + (term-as-dag-aux-ns nil (cdr term) g hcar) + (mv g hcdr (cons h hsl)))))))) + + +;;; We also define a function that makes variables to be shared in a +;;; given graph. More precisely, the following function {\tt +;;; make\--shared\--variables} receives as input a graph, an association +;;; list (associating variables to indices pointing where they appear +;;; for the first time in the graph) and a pair of indices (indicating a +;;; range), and returns a multivalue with a graph where all the +;;; variables in the range of indices are shared and a new computed +;;; association list. Note that during the proccess, if a variable node +;;; is found and the variable is bound in the associaton list to an +;;; index, then the node is updated to that index. If the variable node +;;; is not bound in the association list, then the node is not updated, +;;; but the association list is extended, binding the new variable to +;;; the current index. + + +(local + (defun make-shared-variables (h1 h2 g variables) + (declare (xargs :measure (nfix (- h2 h1)))) + (cond ((zp (- h2 h1)) + (mv g variables)) + ((term-dag-variable-p h1 g) + (let ((bound (assoc (term-dag-symbol h1 g) variables))) + (if bound + (let ((g (update-nth h1 (cdr bound) g))) + (make-shared-variables (1+ h1) h2 g variables)) + (make-shared-variables + (1+ h1) h2 g (acons (term-dag-symbol h1 g) h1 + variables))))) + (t (make-shared-variables (1+ h1) h2 g variables))))) + + +;;; Our strategy is as follows: + +;;; *) +;;; Verify the properties of {\tt term-as-dag-aux-ns}, showing that +;;; stores the input term as a directed acyclic graph. +;;; *) +;;; Show that {\tt make-shared-variables} preserves those properties. +;;; *) +;;; Prove that the composition of {\tt make-shared-variables} and {\tt +;;; term-as-dag-aux-ns} is equal to {\tt term-as-dag-aux} +;;; *) +;;; Combine all the above results to prove the intended properties of +;;; {\tt term-as-dag-aux}. As a particular case, the properties of +;;; {\tt term-as-dag}. +;;; -) + +;;; There is an exception to this strategy: when we prove the {\tt +;;; term-graph-p} property of the graph obtained by {\tt +;;; term-as-dag} (theorem {\tt term-as-dag-term-graph-p} above), +;;; we will reason directly with the definition of the function {\tt +;;; term-as-dag}. + +(local (in-theory (disable assoc-val))) + + +;;; ============================================================================ +;;; +;;; 2) Some properties related to {\tt dag-p} +;;; +;;; ============================================================================ + +;;; One of the main drawbacks in the proof effort described in this book +;;; is the proof that the graphs obtained are acyclic, as defined by the +;;; function @dag-p@ (see {\tt dags.lisp}). In this section we define +;;; some conditions on graphs stronger than the @dag-p@ condition. + + +;;; ----------------------------------- +;;; +;;; 2.1) The property {\tt init-term-dag-p} +;;; +;;; ----------------------------------- + +;;; The property @init-term-dag-p@ defined below describes a particular +;;; type of directed acyclicic graphs: those obtained storing terms +;;; using the function @term-as-dag@. + +;;; Note the style of the definition: we define {\em a property of +;;; nodes} ({\tt property\--element\--init\--term\--dag-p} in this +;;; case). Then we define a function ({\tt init\--term\--dag-p\--aux} in +;;; this case) checking if that property holds in a list of given +;;; nodes. Finally we define the function {\tt init\--term\--dag-p} +;;; checking the property in the list off all the nodes of a graph. + +;;; A graph has the property {\tt init-term-dag-p} if every node is +;;; @nil@, or a compound node such that its arguments are bigger +;;; indices, or a variable node, or an "is" node pointing to a previous +;;; variable node: + +(local + (defun smaller-than-list (h l) + (if (endp l) + t + (and (< h (car l)) + (smaller-than-list h (cdr l)))))) + +(local + (defun property-element-init-term-dag-p (h node g) + (or (and (natp node) (< node h) (term-dag-variable-p node g)) + (equal node nil) + (and (consp node) + (variable-p (car node)) (equal (cdr node) t)) + (and (consp node) + (nat-true-listp (cdr node)) + (smaller-than-list h (cdr node)))))) + +(local + (defun init-term-dag-p-aux (hs g) + (if (endp hs) + t + (and (property-element-init-term-dag-p (car hs) (nth (car hs) g) g) + (init-term-dag-p-aux (cdr hs) g))))) + + +(defun list-from-to (n m) + (declare (xargs :measure (nfix (- m n)) + :guard (and (natp n) (natp m) (<= n m)))) + (if (zp (- m n)) + nil + (cons n (list-from-to (1+ n) m)))) + + + +;;; First, some properties about the function {\tt list-from-to}: + +(local + (defthm list-from-to-main-property + (implies (and (natp n) (natp m)) + (iff (member x (list-from-to n m)) + (and (natp x) (<= n x) (< x m)))))) + + +(local +; Renamed from nat-listp by Matt K. after v4-3, to avoid conflict with +; books/arithmetic/nat-listp.lisp. + (defun local-nat-listp (l) + (if (endp l) + t + (and (natp (car l)) + (local-nat-listp (cdr l)))))) + + +(local + (defthm list-from-to-local-nat-listp + (implies (and (natp h1) (natp h2)) + (local-nat-listp (list-from-to h1 h2))))) + + +(local + (defthm append-list-from-to + (implies (and (natp h1) (natp h2) (natp h3) + (<= h1 h2) (<= h2 h3)) + (equal (append (list-from-to h1 h2) + (list-from-to h2 h3)) + (list-from-to h1 h3))))) + + +(local + (defun init-term-dag-p (g) + (init-term-dag-p-aux (list-from-to 0 (len g)) g))) + + + +;;; ----------------------------------- +;;; +;;; 2.2) The property {\tt tree-p} +;;; +;;; ----------------------------------- + +;;; A particular case of {\tt init\--term\--dag\--p} is the property +;;; {\tt tree-p}. In this case we do not allow "is" nodes. This kind iof +;;; graphs are the graphs built by the function {\tt +;;; term-as-dag-aux-ns}: + +(local + (defun property-element-tree-p (h node) + (or (equal node nil) + (and (consp node) + (variable-p (car node)) (equal (cdr node) t)) + (and (consp node) + (nat-true-listp (cdr node)) + (smaller-than-list h (cdr node)))))) + + + +(local + (defun tree-p-aux (hs g) + (if (endp hs) + t + (and (property-element-tree-p (car hs) (nth (car hs) g)) + (tree-p-aux (cdr hs) g))))) + +(local + (defun tree-p (g) + (tree-p-aux (list-from-to 0 (len g)) g))) + + + + +;;; ----------------------------------- +;;; +;;; 2.2) The property {\tt init-term-dag-p} implies {\tt dag-p} +;;; +;;; ----------------------------------- + +;;; Due to the main properties of {\tt dag-p} (see {\tt dags.lisp}) we +;;; only has to show that every path in graph verifying {\tt +;;; init-term-dag-p} has no duplicates nodes. But this is true because +;;; the paths in this case are strictly increasing except (possibly) the +;;; last node (and in that case, this last node is a variable node and +;;; obvioulsy it has to be the first time it appears in a path): + +;;; We first prove some properties about {\tt init-term-dag-p} before +;;; disabling the function: + +(local + (encapsulate + + () + + (local + (defthm init-term-dag-p-aux-member-1 + (implies (and (init-term-dag-p-aux hs g) + (member h hs) + (not (term-dag-is-p h g))) + (smaller-than-list h (neighbors h g))))) + + (local + (defthm init-term-dag-p-aux-member-2 + (implies (and (member x (neighbors h g)) + (init-term-dag-p-aux hs g) + (member h hs) + (term-dag-is-p h g)) + (not (consp (neighbors x g)))))) + + + (local + (defthm init-term-dag-p-aux-member-3 + (implies (and (init-term-dag-p-aux hs g) + (member h hs)) + (nat-true-listp (neighbors h g))))) + + (local + (defthm nth-non-nil + (implies (and (<= (len l) n) (natp n)) + (not (nth n l))))) + + +;; If a node is not an "is" node, then is smaller than its neighbors. + + (defthm init-term-dag-p-property-1 + (implies (and (natp h) + (init-term-dag-p g) + (not (term-dag-is-p h g))) + (smaller-than-list h (neighbors h g))) + :hints (("Goal" :cases ((< h (len g)))) + ("Subgoal 1" :in-theory (disable neighbors)))) + +;; Non--terminal nodes are not neighbors of an "is" node: + + (defthm init-term-dag-p-property-2 + (implies (and (natp h) + (init-term-dag-p g) + (term-dag-is-p h g) + (consp (neighbors x g))) + (not (member x (neighbors h g)))) + :hints (("Goal" :cases ((< h (len g)))) + ("Subgoal 1" :in-theory (disable neighbors)))) + + +;; The list neighbors of every node is a true list of natural numbers: + + (defthm init-term-dag-p-property-3 + (implies (and (init-term-dag-p g) (natp h)) + (nat-true-listp (neighbors h g))) + :hints (("Goal" :cases ((< h (len g)))) + ("Subgoal 1" :in-theory (disable neighbors)))))) + + + +;;; The three above properties should suffice: + +(local (in-theory (disable neighbors init-term-dag-p))) + + +;;; The following sequence of events show that every path in graph +;;; verifying {\tt init-term-dag-p} has no duplicates. The main idea is +;;; to split every path into two pieces. The first one is a path with +;;; its nodes in a strictly increasing order. The second part is empty +;;; or a variable node that (obviusly) does not appear in the first +;;; part. Both parts has no nodes in common and no duplicate nodes: + + +(local + (encapsulate + () + + (local + (defun strictly-increasing-path-piece (p) + (cond ((or (endp p) (endp (cdr p))) p) + ((< (first p) (second p)) (cons (car p) + (strictly-increasing-path-piece (cdr + p)))) + (t (list (first p)))))) + + (local + (defun remaining-path-piece (p) + (cond ((endp p) p) + ((endp (cdr p)) (cdr p)) + ((< (first p) (second p)) (remaining-path-piece (cdr p))) + (t (cdr p))))) + + (local + (defthm strictly-increasing-path-piece-append-remaining-path-piece + (equal (append (strictly-increasing-path-piece p) + (remaining-path-piece p)) + p))) + + (local + (defun strictly-increasing-list (l) + (cond ((endp l) t) + ((endp (cdr l)) t) + (t (and (< (first l) (second l)) + (strictly-increasing-list (cdr l))))))) + + (local + (defthm strictly-increasing-path-piece-strictly-increasing + (strictly-increasing-list (strictly-increasing-path-piece p)))) + + + (local + (defthm smaller-than-list-main-property + (implies (and (member y l) + (not (< x y))) + (not (smaller-than-list x l))))) + + (local + (defthm map-nfix-true-listp + (implies (nat-true-listp l) + (equal (map-nfix l) l)))) + + (local + (defthm init-term-dag-p-neighbors-main-property + (implies (and (natp h) + (<= x h) + (consp (neighbors x g)) + (init-term-dag-p g)) + (not (member x (neighbors h g)))) + :hints (("Goal" :cases ((term-dag-is-p h g))) + ("Subgoal 2" :use init-term-dag-p-property-1)))) + + + + (local + (defthm remaining-path-piece-main-property + (implies (and (path-p p g) + (init-term-dag-p g) + (not (endp (remaining-path-piece p)))) + (not (consp (neighbors (first (remaining-path-piece p)) g)))))) + + + (local + (defthm path-p-with-its-first-a-terminal-node + (implies (and (path-p p g) + (not (endp (cdr p)))) + (consp (neighbors (first p) g))))) + + + (local + (defthm remaining-path-piece-main-property-corollary + (implies (and (path-p p g) + (init-term-dag-p g) + (not (endp (remaining-path-piece p)))) + (not (consp (cdr (remaining-path-piece p))))))) + + + + (local + (defthm strictly-increasing-path-piece-non-terminal-nodes + (implies (and (path-p p g) + (member x (strictly-increasing-path-piece p)) + (not (endp (remaining-path-piece p)))) + (consp (neighbors x g))))) + + (local + (defthm no-duplicatesp-strictly-increasing + (implies (strictly-increasing-list p) + (no-duplicatesp p)))) + + (local + (defthm no-duplicatesp-unitary + (implies (endp (cdr l)) + (no-duplicatesp l)))) + + + (local + (defthm disjointp-remaining-path-piece-and-strictly-increasing-path-piece + (implies (and (consp (remaining-path-piece p)) + (path-p p g) + (init-term-dag-p g)) + (disjointp (remaining-path-piece p) + (strictly-increasing-path-piece p))) + :hints (("Goal" :expand (disjointp (remaining-path-piece p) + (strictly-increasing-path-piece + p)) + :in-theory (disable disjointp-conmutative)) + ("Goal'" :use remaining-path-piece-main-property)))) + + + (local + (defthm path-p-init-term-dag-p-previous-lemma + (implies (and (path-p p g) + (init-term-dag-p g)) + (no-duplicatesp + (append (strictly-increasing-path-piece p) + (remaining-path-piece p)))) + :hints (("Goal" + :in-theory + (disable + strictly-increasing-path-piece-append-remaining-path-piece) + :cases ((endp (remaining-path-piece p))))))) + + + + (local + (defthm path-p-init-term-dag-p + (implies (and (path-p p g) + (init-term-dag-p g)) + (no-duplicatesp p)) + :hints (("Goal" :use path-p-init-term-dag-p-previous-lemma)))) + + + (defthm init-term-dag-p-implies-dag-p + (implies (init-term-dag-p g) + (dag-p g)) + :hints (("Goal" :use dag-p-soundness))))) + + +;;; ----------------------------------- +;;; +;;; 2.3) The property {\tt tree-p-p} implies {\tt dag-p} +;;; +;;; ----------------------------------- + +;;; This is an easy corollary of the result of the previous section and +;;; the fact that @tree-p@ is a particular case of @init-term-dag-p@: + +(local + (defthm tree-p-aux-implies-init-term-dag-p-aux + (implies (tree-p-aux hs g) + (init-term-dag-p-aux hs g)))) + +(local + (defthm tree-p-implies-init-term-dag-p + (implies (tree-p g) + (init-term-dag-p g)) + :hints (("Goal" :in-theory (enable init-term-dag-p))))) + + +;;; ============================================================================ +;;; +;;; 3) About the {\tt tree-p} property of terms stored with {\tt term\--as\--dag\--aux\--l-ns} +;;; +;;; ============================================================================ + +;;; We now show that, under some conditions, the graph stored by the +;;; function {\tt term-as-dag-aux-ns} has the {\tt tree-p} property: + +;;; First, we are prove some interesting properties about the function +;;; {\tt term-as-dag-aux-ns} that will be useful in general: + +;;; The available index after storing is an integer bigger than the +;;; input index. For terms, it is strictly bigger. + +(local + (defthm term-as-dag-aux-ns-increases-index + (<= h (second (term-as-dag-aux-ns flg term g h))) + :rule-classes :linear)) + +(local + (defthm term-as-dag-aux-ns-increases-index-strictly + (< h (second (term-as-dag-aux-ns t term g h))) + :rule-classes :linear)) + +(local + (defthm term-as-dag-aux-ns-second-value-integerp + (implies (integerp h) + (integerp (second (term-as-dag-aux-ns flg term g h)))))) + +;;; The list of indices returned as the third value is a natural true +;;; list that with all its indices bigger than the input index: + +(local + (defthm term-as-dag-aux-ns-nat-true-listp + (implies (and (natp h) (term-p-aux flg term)) + (nat-true-listp + (third (term-as-dag-aux-ns flg term g h)))))) + +(local + (defthm term-as-dag-aux-ns-smaller-than-list + (implies (and (natp h) (natp h1) (< h h1)) + (smaller-than-list h + (third (term-as-dag-aux-ns nil term g h1)))))) + +;;; The length of the graph finally obtained is bigger (or equal) than +;;; the the first available index returned: + +(local + (defthm len-term-as-dag-aux-ns + (let* ((res (term-as-dag-aux-ns flg term g h)) + (gf (first res)) + (hf (second res))) + (implies (and (natp h) (or flg (consp term))) + (<= hf (len gf)))) + :rule-classes :linear)) + +;;; All the indices in the list returned are smaller than the first +;;; available index returned: + +(local + (defun bigger-than-list (h l) + (if (endp l) + t + (and (> h (car l)) + (bigger-than-list h (cdr l)))))) + + +(local + (defthm term-as-dag-aux-ns-bigger-than-list + (implies (natp h) + (bigger-than-list (second (term-as-dag-aux-ns flg term g h)) + (third (term-as-dag-aux-ns flg term g h)))))) + + + +;;; The following sequence of events leads to show the intended property +;;; for {\tt term-as-dag-aux-ns}. + +;;; The elements above the input index are not modified, so the +;;; @tree-p-aux@ property is preserved: + +(local + (defthm term-as-dag-aux-ns-initial-segment-nth + (implies (and (natp h) (natp h1) (< h h1)) + (equal (nth h (first (term-as-dag-aux-ns flg term g h1))) + (nth h g))))) + + + + +(local + (defthm tree-p-aux-term-as-dag-aux-ns-initial-segment + (implies (and (natp h) (natp h1) (<= h h1)) + (equal (tree-p-aux (list-from-to h h1) + (first (term-as-dag-aux-ns flg term g h1))) + (tree-p-aux (list-from-to h h1) g))))) + + + +;;; Concatenation of list of indices w.r.t. {\tt tree-p-aux}: + +(local + (defthm tree-p-aux-append + (equal (tree-p-aux (append l1 l2) g) + (and (tree-p-aux l1 g) (tree-p-aux l2 g))))) + + + +;;; A particular case, applied to solve one of the induction case of the +;;; theorem below: + +(local + (defthm tree-p-aux-append-particular-case + (let* ((h1 (second (term-as-dag-aux-ns flg1 term1 g1 h))) + (h2 (second (term-as-dag-aux-ns flg2 term2 g2 h1)))) + (implies (natp h) + (equal (tree-p-aux (list-from-to h h2) g3) + (and (tree-p-aux (list-from-to h h1) g3) + (tree-p-aux (list-from-to h1 h2) g3))))) + :hints (("Goal" + :in-theory (disable tree-p-aux-append) + :use + (:instance + tree-p-aux-append + (l1 (list-from-to + h + (second (term-as-dag-aux-ns flg1 term1 g1 h)))) + (l2 (list-from-to + (second + (term-as-dag-aux-ns flg1 term1 g1 h)) + (second + (term-as-dag-aux-ns + flg2 term2 g2 + (second (term-as-dag-aux-ns flg1 term1 g1 h)))))) + + (g g3)))))) + + +;;; Above the first available index, the graph is not modified: + +(local + (defthm term-as-dag-aux-ns-final-segment-nth + (let* ((res (term-as-dag-aux-ns flg term g h1)) + (hf (second res))) + (implies (and (natp h) (<= hf h) (natp h1)) + (equal (nth h (car (term-as-dag-aux-ns flg term g h1))) + (nth h g)))))) + +;;; And finally the intended property about {\tt term-as-dag-aux-ns}: + +(local + (encapsulate + () + (local + (defthm variable-p-property-element-tree-p + (implies (variable-p term) + (property-element-tree-p h (cons term t))))) + + + (local + (defthm compound-node-property-element-tree-p + (implies (and (natp h) (natp h1) (< h h1) (term-p-aux nil term)) + (property-element-tree-p + h + (cons symb (third (term-as-dag-aux-ns nil term g h1))))))) + + + (defthm tree-p-aux-term-as-dag-aux-ns-update-nth + (implies (and (natp h) (natp h1) (< h h1)) + (equal (tree-p-aux (list-from-to h1 h2) + (update-nth h x g)) + (tree-p-aux (list-from-to h1 h2) g)))) + + + (defthm term-as-dag-aux-ns-implies-tree-p-main-lemma + (let* ((res (term-as-dag-aux-ns flg term g h)) + (gf (first res)) + (hf (second res))) + (implies (and (natp h) (term-p-aux flg term)) + (tree-p-aux (list-from-to h hf) gf))) + :hints (("Goal" :in-theory (disable property-element-tree-p)))))) + + +;;; The above property about {\tt tree-p-aux} can be used to prove the +;;; intended property about {\tt tree-p}, but before we need some +;;; technical lemmas: + +(local + (encapsulate + () + + (local + (defthm nth-non-nil + (implies (and (<= (len l) n) (natp n)) + (not (nth n l))))) + + (local + (defthm tree-p-aux-member + (implies (and (tree-p-aux l g) (member x l)) + (property-element-tree-p x (nth x g))) + :rule-classes nil)) + + + + + (defthm tree-p-aux-property-element-p + (implies (and (tree-p g) (natp h)) + (property-element-tree-p h (nth h g))) + :hints (("Goal" :cases ((< h (len g)))) + ("Subgoal 1" :use + (:instance tree-p-aux-member + (x h) + (l (list-from-to 0 (len g))))))))) + + +;;; The following sequence of events show the intended result: + +(local + (encapsulate + () + + (local + (defthm term-as-dag-aux-ns-implies-tree-p-initial-segment + (let* ((res (term-as-dag-aux-ns flg term g h)) + (gf (first res))) + (implies (and (natp h) (tree-p g) (subsetp l (list-from-to 0 h))) + (tree-p-aux l gf))) + :hints (("Goal" + :induct (len l) + :in-theory (disable property-element-tree-p))))) + + (local + (defthm term-as-dag-aux-ns-implies-tree-p-final-segment + (let* ((res (term-as-dag-aux-ns flg term g h)) + (gf (first res)) + (hf (second res))) + (implies (and (natp h) (tree-p g) (subsetp l (list-from-to hf (len gf)))) + (tree-p-aux l gf))) + :hints (("Goal" + :induct (len l) + :in-theory (disable property-element-tree-p))))) + + (local + (defthm term-as-dag-aux-ns-implies-tree-p-almost + (let* ((res (term-as-dag-aux-ns flg term g h)) + (gf (first res)) + (hf (second res)) + (l1 (list-from-to 0 h)) + (l2 (list-from-to h hf)) + (l3 (list-from-to hf (len gf)))) + (implies (and (natp h) (tree-p g) (term-p-aux flg term)) + (tree-p-aux (append l1 (append l2 l3)) gf))) + :rule-classes nil)) + + +;; This is the intended result of this section: the term stored by {\tt +;; term-as-dag-aux-ns} verifies {\tt tree-p}: + + (defthm term-as-dag-aux-ns-implies-tree-p + (implies (and (natp h) + (tree-p g) + (term-p-aux flg term)) + (tree-p (first (term-as-dag-aux-ns flg term g h)))) + :hints (("Goal" + :cases ((and (not flg) (not (consp term))))) + ("Subgoal 2" + :in-theory (disable + tree-p-aux-append + append-list-from-to) + :use + (term-as-dag-aux-ns-implies-tree-p-almost + (:instance append-list-from-to + (h1 0) (h2 h) + (h3 (cadr (term-as-dag-aux-ns flg term g h)))) + (:instance append-list-from-to + (h1 h) + (h2 (cadr (term-as-dag-aux-ns flg term g h))) + (h3 (len (car (term-as-dag-aux-ns flg term g h))))) + (:instance append-list-from-to + (h1 0) (h2 h) + (h3 (len (car (term-as-dag-aux-ns flg term g h))))))))))) + + +;;; ============================================================================ +;;; +;;; 4) The term stored using {\tt term-as-dag-aux-ns} is the input term +;;; +;;; ============================================================================ + +;;; In this section we show that {\tt term-as-dag-aux-ns} builds a +;;; graph that represents the input term. That is, we want to show the +;;; following theorem: + +; (defthm term-as-dag-aux-ns-dag-as-term-aux-relationship +; (let* ((res (term-as-dag-aux-ns flg term g h)) +; (g-ret (first res)) +; (hs-ret (third res))) +; (implies (and (natp h) +; (term-p-aux flg term) +; (tree-p g)) +; (equal (dag-as-term flg (if flg h hs-ret) g-ret) +; term)))) + + +;;; We consider three stage in our proof: + +;;; *) +;;; First we show how the {\tt tree-p} property is related to updating +;;; the graph. This is esssential to be able to use induction +;;; hypothesis in the proof of the main result. +;;; *) +;;; Then we introduce the notion of subgraph, and coincidence in a list +;;; of indices. We show that when two graphs coincide in a subgraph, +;;; then the terms stored are the same. +;;; *) +;;; The above property can be used to use the induction hypothesis in +;;; the proof of the main theorem, since, for example, it allows to use +;;; the value of {\tt dag-as-term} in the rest of arguments of a list +;;; of terms. +;;; *) +;;; We prove the main theorem by induction on the structure of terms. +;;; -) + + + +;;; ----------------------------------- +;;; +;;; 4.1) The property {\tt tree-p} when updating a graph +;;; +;;; ----------------------------------- + +;;; The following sequence of events are needed to prove the theorems +;;; {\tt tree-p-update-nth-variables} and {\tt +;;; tree-p-update-nth-smaller-than-list} below, showing how the {\tt +;;; tree-p} property is preserved by the updatings done during the +;;; proccess of {\tt terms-as-dag-l-ns}: + +(local + (encapsulate + + () + + + (local + (defthm len-update-nth-2 + (implies (natp h) (<= (1+ h) (len (update-nth h x g)))) + :rule-classes :linear)) + + + (local + (defthm property-element-tree-p-variable-p + (implies (variable-p term) + (property-element-tree-p h (cons term t))))) + + (local + (defthm tree-p-aux-update-nth-variables + (implies (and (tree-p-aux hs g) (variable-p term)) + (tree-p-aux hs (update-nth h (cons term t) g))) + :hints (("Goal" :in-theory (disable property-element-tree-p) + :induct (len hs))))) + + (local + (defthm nth-non-nil + (implies (and (<= (len l) n) (natp n)) + (not (nth n l))))) + + (local + (defthm tree-p-aux-list-from-to-beyond-length-lemma + (implies (and (<= (len g) h1) + (natp h1) + (subsetp hs (list-from-to (len g) h1))) + (tree-p-aux hs g)))) + + (local + (defthm tree-p-aux-list-from-to-beyond-length + (implies (and (natp h1) (<= (len g) h1) + (tree-p-aux (list-from-to 0 (len g)) g)) + (tree-p-aux (list-from-to 0 h1) g)) + :hints (("Goal" + :in-theory (disable + tree-p-aux-append + append-list-from-to) + :use + ((:instance append-list-from-to + (h1 0) (h2 (len g)) (h3 h1)) + (:instance tree-p-aux-append + (l1 (list-from-to 0 (len g))) + (l2 (list-from-to (len g) h1)))))) + :rule-classes nil)) + + (local + (defthm property-element-tree-p-smaller-than-list + (implies (and (nat-true-listp l) + (smaller-than-list h l)) + (property-element-tree-p h (cons x l))))) + + + (local + (defthm tree-p-aux-update-nth-smaller-than-list + (implies (and (tree-p-aux hs g) + (natp h) + (local-nat-listp hs) + (nat-true-listp l) + (smaller-than-list h l)) + (tree-p-aux hs (update-nth h (cons x l) g))) + :hints (("Goal" :in-theory (disable property-element-tree-p) + :induct (len hs))))) + + +;; These are the main theorems in this subsection, establishing that the +;; {\tt tree-p} property is preserved after updating the graph like our +;; function does: + + (defthm tree-p-update-nth-variables + (implies (and (tree-p g) (variable-p term) (natp h)) + (tree-p (update-nth h (cons term t) g))) + :hints (("Goal" + :use + (:instance tree-p-aux-list-from-to-beyond-length + (h1 (len (update-nth h (cons term t) g))))))) + + + (defthm tree-p-update-nth-smaller-than-list + (implies (and (tree-p g) (natp h) + (nat-true-listp l) + (smaller-than-list h l)) + (tree-p (update-nth h (cons x l) g))) + :hints (("Goal" :use + (:instance tree-p-aux-list-from-to-beyond-length + (h1 (len (update-nth h (cons x l) g))))))))) + +;;; All the needed properties about {\tt tree-p} are now extracted: + +(local (in-theory (disable tree-p))) + + +;;; ----------------------------------- +;;; +;;; 4.2) Subgraphs and coincidence in subgraphs. +;;; +;;; ----------------------------------- + +;;; When proving (by induction on the structure of terms) the main +;;; theorem of this section, one of the induction case is a to prove the +;;; result for non--empty list of terms, having as induction hypothesis +;;; the result for the first term and the result for the list of the +;;; rest of terms. To be able to use the first hypothesis, we must show +;;; that the first term after completing the process it is stored in the +;;; same way as before storing the rest of the terms. And this is true +;;; because every time a subterm is stored in the graph, it is stored in +;;; a subgraph, and subgraphs are "closed" w.r.t. the terms +;;; stored. We prove this in this subsection. + + +;;; Let us first define the notion of {\em subgraph}. The following +;;; function checks that that all the neighbors (in a graph @g@) of a +;;; list of nodes @hs1@ are a subset of the list of nodes @hs2@: + +(local + (defun subsetp-all-neighbors (hs1 hs2 g) + (if (endp hs1) + t + (and (subsetp (neighbors (car hs1) g) hs2) + (subsetp-all-neighbors (cdr hs1) hs2 g))))) + +;;; A list of nodes @hs@ is a subgraph of a graph @g@ if all the +;;; neighbors of the nodes of the list are in the same list. + +(local + (defun subgraph-p (hs g) + (subsetp-all-neighbors hs hs g))) + +;;; The following function define the notion of {\em coincidence} in a +;;; set of indices of two given graphs. + +(local + (defun graph-coincide (hs g1 g2) + (if (endp hs) + t + (and (equal (nth (car hs) g1) (nth (car hs) g2)) + (graph-coincide (cdr hs) g1 g2))))) + + +;;; Now we show that if we have two directed acyclic graphs such that a +;;; given set of indices form a subgraph and coincide in both subgraphs, +;;; then the function @dag-as-term@ behaves in the same way in both +;;; subgraphs, for every index of the subgraph. The following sequence +;;; of events show this (theorem {\tt +;;; dag-as-term-equal-when-coincide-in-subgraphs} below): + +(local + (encapsulate + () + + (local + (defthm graph-coincide-forward-chaining + (implies (and (graph-coincide hs g1 g2) + (member h hs)) + (equal (nth h g1) (nth h g2))) + :rule-classes :forward-chaining)) + + (local (in-theory (enable neighbors))) + + (local + (defthm subsetp-coincide-property-1 + (implies (and (subsetp-all-neighbors hs1 hs2 g) + (not (term-dag-variable-p h g)) + (not (term-dag-is-p h g)) + (member h hs1)) + (subsetp (term-dag-args h g) hs2)))) + + (local + (defthm subsetp-coincide-property-2 + (implies (and (subsetp-all-neighbors hs1 hs2 g) + (term-dag-is-p h g) + (member h hs1)) + (member (nth h g) hs2)))) + + (defthm subsetp-all-neighbors-forward-chaining + (implies (and (subsetp-all-neighbors hs1 hs2 g1) + (graph-coincide hs1 g1 g2)) + (subsetp-all-neighbors hs1 hs2 g2)) + :rule-classes (:forward-chaining :rewrite)) + + (local (in-theory (disable neighbors))) + + + (defthm dag-as-term-equal-when-coincide-in-subgraphs + (implies (and (subgraph-p hs g1) + (graph-coincide hs g1 g2) + (dag-p g1) (dag-p g2) + (if flg (member h hs) (subsetp h hs))) + (equal (dag-as-term flg h g1) + (dag-as-term flg h g2))) + :rule-classes :forward-chaining))) + + +;;; ----------------------------------- +;;; +;;; 4.3) Subgraphs and coincidence in {\tt term-as-dag-aux-ns} +;;; +;;; ----------------------------------- + +;;; We prove now that the terms stored by {\tt term-as-dag-aux-ns} are +;;; subgraphs of the entire graph. And we also prove that if two terms +;;; are stored sequentially, then the graph obtained after storing the +;;; first term coincide, in the subgraph corresponding to that subterm, +;;; with the graph obtained after succesively storing the first and then +;;; the second. + +;;; In this way, we can use the result in the previous subsection to +;;; prove two theorems that will allow us to use the induction +;;; hypothesis in the proof of the main theorem in this section. + +;;; First, we show the result about coincidence of graphs obtained after +;;; storing two terms sequentially: + +(local + (defthm graph-coincide-term-as-dag-aux-ns + (implies (and (natp h) + (subsetp + hs + (list-from-to h (second (term-as-dag-aux-ns flg1 term1 g h))))) + (graph-coincide + hs + (first (term-as-dag-aux-ns flg1 term1 g h)) + (first (term-as-dag-aux-ns + flg2 term2 + (first (term-as-dag-aux-ns flg1 term1 g h)) + (second (term-as-dag-aux-ns flg1 term1 g h)))))) + :hints (("Goal" :induct (len hs))))) + + + +;;; And now, the following sequence of events show that the nodes of the +;;; graph used to store a term are a subgraph of the entire graph: + +(local + (encapsulate + () + (local + (defthm subsetp-all-neighbors-append + (implies (and (subsetp-all-neighbors hs11 hs12 g) + (subsetp-all-neighbors hs21 hs22 g)) + (subsetp-all-neighbors (append hs11 hs21) + (append hs12 hs22) + g)))) + + (local + (defthm very-ugly-lemma + (let* ((ret-term1 (term-as-dag-aux-ns t term1 g h)) + (g-term1 (first ret-term1)) + (h1 (second ret-term1)) + (ret-term2 (term-as-dag-aux-ns nil term2 g-term1 h1)) + (g-term2 (first ret-term2)) + (h2 (second ret-term2)) + (l1 (list-from-to h h1)) + (l2 (list-from-to h1 h2)) + (l (list-from-to h h2))) + (implies (and (natp h) + (subsetp-all-neighbors l1 l1 g-term2) + (subsetp-all-neighbors l2 l2 g-term2)) + (subsetp-all-neighbors l l g-term2))) + :hints (("Goal" :use + (:instance + subsetp-all-neighbors-append + (hs11 (list-from-to h (second (term-as-dag-aux-ns t term1 g h)))) + (hs12 (list-from-to h (second (term-as-dag-aux-ns t term1 g h)))) + (hs21 (list-from-to + (second (term-as-dag-aux-ns t term1 g h)) + (second (term-as-dag-aux-ns + nil term2 + (first (term-as-dag-aux-ns t term1 g h)) + (second (term-as-dag-aux-ns t term1 g h)))))) + (hs22 (list-from-to + (second (term-as-dag-aux-ns t term1 g h)) + (second (term-as-dag-aux-ns + nil term2 + (first (term-as-dag-aux-ns t term1 g h)) + (second (term-as-dag-aux-ns t + term1 g h)))))) + (g (first (term-as-dag-aux-ns + nil term2 + (first (term-as-dag-aux-ns t term1 g h)) + (second (term-as-dag-aux-ns t term1 g + h)))))))))) + + + + (local + (defthm subsetp-all-neighbors-coincide-particular-case + (let* ((ret-term (term-as-dag-aux-ns flg term g h)) + (g-term1 (first ret-term)) + (h1 (second ret-term)) + (hs (list-from-to h h1)) + (g-term2 (first (term-as-dag-aux-ns flg2 term2 g-term1 h1)))) + (implies (and (natp h) (subsetp-all-neighbors hs hs g-term1)) + (subsetp-all-neighbors hs hs g-term2))))) + + (local + (defthm subsetp-all-neighbors-cons-second-argument-lemma + (implies (subsetp-all-neighbors l1 l2 g) + (subsetp-all-neighbors l1 (cons x l2) g)))) + + (local + (defthm subsetp-all-neighbors-cons-second-argument + (implies (and (subsetp (neighbors x g) l) + (subsetp-all-neighbors l l g)) + (subsetp-all-neighbors (cons x l) (cons x l) g)))) + + (local + (defthm subsetp-all-neighbors-update-nth-not-member + (implies (and (not (member h hs1)) + (natp h) + (nat-true-listp hs1) + (subsetp-all-neighbors hs1 hs2 g)) + (subsetp-all-neighbors hs1 hs2 (update-nth h x g))) + :hints (("Goal" :in-theory (enable neighbors))))) + + (local + (defthm nat-true-listp-list-from-to + (implies (natp h) + (nat-true-listp (list-from-to h h1))))) + + (defthm term-as-dag-aux-ns-local-nat-listp + (let* ((res (term-as-dag-aux-ns flg term g h)) + (hs-ret (third res))) + (implies (natp h) + (local-nat-listp hs-ret)))) + + (defthm subsetp-list-from-to + (implies + (and (natp h1) (natp h2) + (local-nat-listp hs) + (smaller-than-list h1 hs) + (bigger-than-list h2 hs)) + (subsetp hs (list-from-to (1+ h1) h2)))) + + (defthm subgraph-p-term-as-dag-aux-ns + (implies (natp h) + (subgraph-p + (list-from-to + h + (second (term-as-dag-aux-ns flg term g h))) + (first (term-as-dag-aux-ns flg term g h)))) + :hints (("Goal" :in-theory (enable neighbors)))))) + + +(local (in-theory (disable subgraph-p))) + + + +;;; ----------------------------------- +;;; +;;; 4.4) The main result of this section +;;; +;;; ----------------------------------- + + +;;; We apply the results of the previous subsections to prove the main +;;; lemmas needed to deal with two induction hypothesis in the proof of +;;; the main result of this subsection. + + +(local + (encapsulate + () + +;; This lemma allows to use one the induction hypothesis (the one for +;; the first term of the list) in the induction case corresponding to +;; non-empty list of terms: + + (local + (defthm equal-dag-as-term-composition-of-term-as-dag + (let* ((ret-term1 (term-as-dag-aux-ns t term1 g h)) + (g-term1 (first ret-term1)) + (h1 (second ret-term1)) + (ret-term2 (term-as-dag-aux-ns nil term2 g-term1 h1)) + (g-term2 (first ret-term2))) + (implies (and (natp h) (tree-p g) + (term-p-aux t term1) (term-p-aux nil term2)) + (equal (dag-as-term t h g-term2) + (dag-as-term t h g-term1)))) + :hints (("Goal" :use + (:instance + dag-as-term-equal-when-coincide-in-subgraphs + (flg t) + (g1 (first (term-as-dag-aux-ns t term1 g h))) + (g2 (first + (term-as-dag-aux-ns + nil term2 + (first + (term-as-dag-aux-ns t term1 g h)) + (second (term-as-dag-aux-ns t term1 g h))))) + + (hs (list-from-to + h (second (term-as-dag-aux-ns t term1 g h))))))))) + + (local + (defthm graph-coincide-update-nth + (implies (and (not (member h hs)) (natp h) (local-nat-listp hs)) + (graph-coincide hs g (update-nth h x g))))) + + (local + (defthm list-from-to-local-nat-listp + (implies (and (natp h1) (natp h2)) + (local-nat-listp (list-from-to h1 h2))))) + + + +;; And this lemma allows to use the induction hypothesis (the one for +;; the list of its arguments) corresponding to the induction case of +;; non-variable terms: + + + (local + (defthm equal-dag-as-term-update-nth + (implies + (and (natp h) + (term-p-aux nil term) + (tree-p g)) + (equal + (dag-as-term + nil + (third (term-as-dag-aux-ns nil term g (+ 1 h))) + (update-nth h + (cons f (third (term-as-dag-aux-ns nil term g (1+ h)))) + (first (term-as-dag-aux-ns nil term g (+ 1 h))))) + (dag-as-term + nil + (third (term-as-dag-aux-ns nil term g (+ 1 h))) + (first (term-as-dag-aux-ns nil term g (+ 1 h)))))) + :hints + (("Goal" + :use + (:instance + dag-as-term-equal-when-coincide-in-subgraphs + (flg nil) + (h (third (term-as-dag-aux-ns nil term g (+ 1 h)))) + (g1 (first (term-as-dag-aux-ns nil term g (+ 1 h)))) + (g2 (update-nth + h + (cons f (third (term-as-dag-aux-ns nil term g (1+ h)))) + (first (term-as-dag-aux-ns nil term g (+ 1 h))))) + (hs (list-from-to + (1+ h) + (second (term-as-dag-aux-ns nil term g (+ 1 h)))))))))) + +;; And finally the intended result of this section: + + (local + (defthm term-as-dag-aux-ns-dag-as-term-aux-relationship + (let* ((res (term-as-dag-aux-ns flg term g h)) + (g-ret (first res)) + (hs-ret (third res))) + (implies (and (natp h) + (term-p-aux flg term) + (tree-p g)) + (equal (dag-as-term flg (if flg h hs-ret) g-ret) + term))) + :rule-classes nil)) + +;; This result is better used in form of a rewriting rule: + + (defthm term-as-dag-aux-ns-dag-as-term-aux-relationship-rewrite-rule + (let* ((res (term-as-dag-aux-ns flg term g h)) + (g-ret (first res)) + (hs-ret (third res))) + (implies (and (natp h) + (term-p-aux flg term) + (tree-p g) + (equal h1 (if flg h hs-ret))) + (equal (dag-as-term flg h1 g-ret) + term))) + :hints (("Goal" + :use term-as-dag-aux-ns-dag-as-term-aux-relationship))))) + + +;;; ============================================================================ +;;; +;;; 5) Relationship between {\tt terms\--as\--dag\--aux\--l-ns} and {\tt terms\--as-dag\--aux\--l} +;;; +;;; ============================================================================ + +;;; Our goal in this subsection is to prove the following theorem: + + +; (defthm term-as-dag-aux-in-two-steps +; (let* ((res1 (term-as-dag-aux flg term g h variables)) +; (g-ret1 (first res1)) +; (res2 (term-as-dag-aux-ns flg term g h)) +; (g-ret2 (first res2)) +; (h-ret2 (second res2))) +; (implies (and (natp h) +; (term-p-aux flg term)) +; (equal g-ret1 +; (first (make-shared-variables h h-ret2 g-ret2 variables)))) + +;;; That is, we are going to prove that the graph obtained after storing +;;; a term using the function {\tt term-as-dag-aux} is the same than +;;; the graph obtained storing the same term with {\tt +;;; term-as-dag-aux-ns} and after that applying {\tt +;;; make-shared-variables}. + + + +;;; The following two properties show that the second value returned by +;;; term-as-dag-aux is a natural number (that is, the first available +;;; index after storing the graph). + +(local + (defthm integerp-term-as-dag-aux + (implies (integerp h) + (integerp (second (term-as-dag-aux flg term g h variables)))))) + +(local + (defthm integerp-term-as-dag-aux-natp + (implies (natp h) + (>= (second (term-as-dag-aux flg term g h variables)) 0)) + :rule-classes :linear)) + + + +;;; Now we establish some properties about the function {\tt +;;; make-shared-variables} (see its definition in Section 1): + + +;;; First, a property about updating the result of a {\tt +;;; make-shared-variables} outside the range where the sharing of +;;; variables occur. + +(local + (defthm update-nth-update-nth-disjoint + (implies (and (natp h1) (natp h2) (< h2 h1)) + (equal (update-nth h1 x (update-nth h2 y g)) + (update-nth h2 y (update-nth h1 x g)))))) + + +(local + (defthm make-shared-variables-update-nth-disjoint-graph + (implies + (and (natp h) (natp h1) (natp h2) (< h h1) (<= h1 h2)) + (equal + (first (make-shared-variables + h1 h2 (update-nth h x g) variables)) + (update-nth h x (first (make-shared-variables h1 h2 g variables))))) + :hints (("Goal" :induct (make-shared-variables h1 h2 g variables)) + ("Subgoal *1/4.2" :expand (make-shared-variables h1 h2 (update-nth h x g) + variables)) + ("Subgoal *1/3.2" :expand (make-shared-variables h1 h2 (update-nth h x g) + variables)) + ("Subgoal *1/2.2" :expand (make-shared-variables h1 h2 (update-nth h x g) + variables))))) + +;;; A fundamental lemma, describing how make shared variables can be +;;; done in several stages: + +(local + (defthm make-shared-composition + (implies (and (<= h1 h2) (<= h2 h3) + (natp h1) (natp h2) (natp h3)) + (equal (make-shared-variables h1 h3 g variables) + (make-shared-variables + h2 h3 + (first (make-shared-variables h1 h2 g variables)) + (second (make-shared-variables h1 h2 g variables))))) + :rule-classes nil)) + +;;; The following two lemmas show that some nodes of the original graph +;;; do not change after making the variables shared: + + +(local + (defthm nth-make-shared-variables + (implies (and (natp h) (natp h1) (natp h2) (< h h1)) + (equal (nth h + (car + (make-shared-variables h1 h2 g variables))) + (nth h g))))) + + +(local + (defthm make-shared-variables-does-not-change-non-variables + (implies (not (term-dag-variable-p h g)) + (equal (nth + h + (first (make-shared-variables h1 h2 g variables))) + (nth h g))))) + + + +;;; The following @encapsulate@ contains the lemmas and definitions +;;; needed to deal with all the induction cases of the goal theorem in +;;; this section. + + + +(local + (encapsulate + () + (local + (defun induct-hint-for-last-index-independent-of-graph + (flg term g1 g2 h) + (if flg + (if (variable-p term) + (list g1 g2 h) + (induct-hint-for-last-index-independent-of-graph + nil (cdr term) g1 g2 (1+ h))) + (if (endp term) + t + (mv-let (g1-n hcar ign) + (term-as-dag-aux-ns t (car term) g1 h) + (declare (ignore ign)) + (mv-let (g2-n ign1 ign2) + (term-as-dag-aux-ns t (car term) g2 h) + (declare (ignore ign1 ign2)) + (and (induct-hint-for-last-index-independent-of-graph + t (car term) g1 g2 h) + (induct-hint-for-last-index-independent-of-graph + nil (cdr term) g1-n g2-n hcar)))))))) + + +;; The second and third values returned by {\tt term-as-dag-aux-ns} do +;; not depend on the graph: + + (local + (defthm last-index-independent-of-graph + (and + (equal (second (term-as-dag-aux-ns flg term g1 h)) + (second (term-as-dag-aux-ns flg term g2 h))) + (equal (third (term-as-dag-aux-ns flg term g1 h)) + (third (term-as-dag-aux-ns flg term g2 h)))) + + :hints (("Goal" + :induct + (induct-hint-for-last-index-independent-of-graph + flg term g1 g2 h))) + :rule-classes nil)) + + +;; The second and third values returned by {\tt term-as-dag-aux-ns} +;; and {\tt term-as-dag-aux} are the same: + + + (local + (defthm term-as-dag-aux-ns-term-as-dag-aux-equal-second-argument + (equal (second (term-as-dag-aux flg term g h variables)) + (second (term-as-dag-aux-ns flg term g h))) + :hints (("Subgoal *1/4'''" :use + (:instance last-index-independent-of-graph + (flg nil) (term term2) + (h (cadr (term-as-dag-aux-ns t term1 g h))) + (g1 (car (term-as-dag-aux t term1 g h + variables))) + (g2 (car (term-as-dag-aux-ns t term1 g h)))))))) + + (local + (defthm term-as-dag-aux-ns-term-as-dag-aux-equal-third-argument + (equal (third (term-as-dag-aux flg term g h variables)) + (third (term-as-dag-aux-ns flg term g h))) + :hints (("Subgoal *1/4'''" :use + (:instance last-index-independent-of-graph + (flg nil) (term term2) + (h (cadr (term-as-dag-aux-ns t term1 g h))) + (g1 (car (term-as-dag-aux t term1 g h + variables))) + (g2 (car (term-as-dag-aux-ns t term1 g h)))))))) + + + +;; The following (very long lemmas) deal with induction case 4 of the +;; induction proof of our main goal: + + (local + (defthm last-index-independent-of-graph-particular-case + (equal + (cadr + (term-as-dag-aux-ns nil term2 + (car (term-as-dag-aux t term1 g h variables)) + (cadr (term-as-dag-aux-ns t term1 g h)))) + + (cadr (term-as-dag-aux-ns nil term2 + (car (term-as-dag-aux-ns t term1 g h)) + (cadr (term-as-dag-aux-ns t term1 g + h))))) + :hints (("Goal" + :use + (:instance last-index-independent-of-graph + (flg nil) (term term2) + (h (cadr (term-as-dag-aux-ns t term1 g h))) + (g1 (car (term-as-dag-aux t term1 g h + variables))) + (g2 (car (term-as-dag-aux-ns t term1 g h)))))))) + + (local + (defthm update-nth-term-as-dag-aux-ns-below + (implies (and (natp h1) (natp h2) (< h1 h2)) + (equal + (first (term-as-dag-aux-ns + flg term (update-nth h1 x g) h2)) + (update-nth h1 x + (first (term-as-dag-aux-ns + flg term g h2))))) + :hints (("Goal" :induct (term-as-dag-aux-ns + flg term g h2)) + ("Subgoal *1/4.1'" + :use (:instance last-index-independent-of-graph + (flg t) (term term1) + (h h2) + (g1 (update-nth h1 x g)) (g2 g))) + ("Subgoal *1/2.1''" + :use (:instance last-index-independent-of-graph + (flg nil) (term term2) (g1 g) (h (+ 1 h2)) + (g2 (update-nth h1 x g))))))) + + (local + (defthm make-shared-variables-terms-as-dag-aux-l-ns-graph + (implies (and (natp h1) (natp h2)) + (equal (first + (make-shared-variables + h1 h2 + (car (term-as-dag-aux-ns flg term g h2)) + variables)) + (first + (term-as-dag-aux-ns + flg term (car (make-shared-variables h1 h2 g + variables)) + h2)))))) + + (local + (defthm make-shared-variables-terms-as-dag-aux-l-ns-variables + (implies (and (natp h1) (natp h2)) + (equal (second + (make-shared-variables + h1 h2 + (car (term-as-dag-aux-ns flg term g h2)) + variables)) + (second + (make-shared-variables h1 h2 g variables)))) + :hints (("Goal" :induct (make-shared-variables h1 h2 g variables))))) + + + (local + (defthm induction-case-4-term-as-dag-aux-in-two-steps-graph + (implies + (and + (equal + (first (make-shared-variables h + (second (term-as-dag-aux-ns t term1 g h)) + (first (term-as-dag-aux-ns t term1 g h)) + variables)) + (first (term-as-dag-aux t term1 g h variables))) + (equal + (second (make-shared-variables h + (second (term-as-dag-aux-ns t term1 g h)) + (first (term-as-dag-aux-ns t term1 g h)) + variables)) + (fourth (term-as-dag-aux t term1 g h variables))) + (equal + (first + (make-shared-variables + (second (term-as-dag-aux-ns t term1 g h)) + (second + (term-as-dag-aux-ns nil term2 + (first (term-as-dag-aux t term1 g h variables)) + (second (term-as-dag-aux-ns t term1 g h)))) + (first + (term-as-dag-aux-ns nil term2 + (first (term-as-dag-aux t term1 g h variables)) + (second (term-as-dag-aux-ns t term1 g h)))) + (fourth (term-as-dag-aux t term1 g h variables)))) + (first + (term-as-dag-aux nil term2 + (first (term-as-dag-aux t term1 g h variables)) + (second (term-as-dag-aux-ns t term1 g h)) + (fourth (term-as-dag-aux t term1 g h variables))))) + (equal + (second + (make-shared-variables + (second (term-as-dag-aux-ns t term1 g h)) + (second + (term-as-dag-aux-ns nil term2 + (first (term-as-dag-aux t term1 g h variables)) + (second (term-as-dag-aux-ns t term1 g h)))) + (first + (term-as-dag-aux-ns nil term2 + (first (term-as-dag-aux t term1 g h variables)) + (second (term-as-dag-aux-ns t term1 g h)))) + (fourth (term-as-dag-aux t term1 g h variables)))) + (fourth + (term-as-dag-aux nil term2 + (first (term-as-dag-aux t term1 g h variables)) + (second (term-as-dag-aux-ns t term1 g h)) + (fourth (term-as-dag-aux t term1 g h variables))))) + (natp h)) + (equal + (first + (make-shared-variables + h + (second (term-as-dag-aux-ns nil term2 + (first (term-as-dag-aux-ns t term1 g h)) + (second (term-as-dag-aux-ns t term1 g h)))) + (first (term-as-dag-aux-ns nil term2 + (first (term-as-dag-aux-ns t term1 g h)) + (second (term-as-dag-aux-ns t term1 g h)))) + variables)) + (first + (term-as-dag-aux nil term2 + (first (term-as-dag-aux t term1 g h variables)) + (second (term-as-dag-aux-ns t term1 g h)) + (fourth (term-as-dag-aux t term1 g h variables)))))) + :hints (("Goal" :use + (:instance make-shared-composition + (h1 h) + (h2 (cadr (term-as-dag-aux-ns t term1 g h))) + (h3 (cadr (term-as-dag-aux-ns + nil term2 + (car (term-as-dag-aux-ns t term1 g h)) + (cadr (term-as-dag-aux-ns t term1 g h))))) + (g (car (term-as-dag-aux-ns + nil term2 + (car (term-as-dag-aux-ns t term1 g h)) + (cadr (term-as-dag-aux-ns t term1 g h)))))))))) + + + + (local + (defthm induction-case-4-term-as-dag-aux-in-two-steps-variable + (implies + (and + (equal + (first (make-shared-variables h + (second (term-as-dag-aux-ns t term1 g h)) + (first (term-as-dag-aux-ns t term1 g h)) + variables)) + (first (term-as-dag-aux t term1 g h variables))) + (equal + (second (make-shared-variables h + (second (term-as-dag-aux-ns t term1 g h)) + (first (term-as-dag-aux-ns t term1 g h)) + variables)) + (fourth (term-as-dag-aux t term1 g h variables))) + (equal + (first + (make-shared-variables + (second (term-as-dag-aux-ns t term1 g h)) + (second (term-as-dag-aux-ns nil term2 + (first (term-as-dag-aux-ns t term1 g h)) + (second (term-as-dag-aux-ns t term1 g h)))) + (first + (term-as-dag-aux-ns nil term2 + (first (term-as-dag-aux t term1 g h variables)) + (second (term-as-dag-aux-ns t term1 g h)))) + (fourth (term-as-dag-aux t term1 g h variables)))) + (first + (term-as-dag-aux nil term2 + (first (term-as-dag-aux t term1 g h variables)) + (second (term-as-dag-aux-ns t term1 g h)) + (fourth (term-as-dag-aux t term1 g h variables))))) + (equal + (second + (make-shared-variables + (second (term-as-dag-aux-ns t term1 g h)) + (second (term-as-dag-aux-ns nil term2 + (first (term-as-dag-aux-ns t term1 g h)) + (second (term-as-dag-aux-ns t term1 g h)))) + (first + (term-as-dag-aux-ns nil term2 + (first (term-as-dag-aux t term1 g h variables)) + (second (term-as-dag-aux-ns t term1 g h)))) + (fourth (term-as-dag-aux t term1 g h variables)))) + (fourth + (term-as-dag-aux nil term2 + (first (term-as-dag-aux t term1 g h variables)) + (second (term-as-dag-aux-ns t term1 g h)) + (fourth (term-as-dag-aux t term1 g h variables))))) + (natp h)) + (equal + (second + (make-shared-variables + h + (second (term-as-dag-aux-ns nil term2 + (first (term-as-dag-aux-ns t term1 g h)) + (second (term-as-dag-aux-ns t term1 g h)))) + (first (term-as-dag-aux-ns nil term2 + (first (term-as-dag-aux-ns t term1 g h)) + (second (term-as-dag-aux-ns t term1 g h)))) + variables)) + (fourth + (term-as-dag-aux nil term2 + (first (term-as-dag-aux t term1 g h variables)) + (second (term-as-dag-aux-ns t term1 g h)) + (fourth (term-as-dag-aux t term1 g h + variables)))))) + :hints (("Goal" :use + (:instance + make-shared-composition + (h1 h) + (h2 (second (term-as-dag-aux-ns t term1 g h))) + (h3 (second (term-as-dag-aux-ns + nil term2 + (first (term-as-dag-aux-ns t term1 g h)) + (second (term-as-dag-aux-ns t term1 g h))))) + (g (first (term-as-dag-aux-ns + nil term2 + (first (term-as-dag-aux-ns t term1 g h)) + (second (term-as-dag-aux-ns t term1 g h)))))))))) + + +;; The following deal with induction case 2 of the induction proof of +;; our main goal: + + + (local + (defthm update-nth-update-nth-at-the-same-index + (equal (update-nth h y (update-nth h x g)) + (update-nth h y g)))) + + + (local + (defthm make-shared-variables-non-variable-term + (implies + (and (natp h) (natp h2) (<= h h2) + (nat-true-listp l)) + (equal + (make-shared-variables + h h2 (update-nth h (cons f l) g) variables) + (make-shared-variables + (1+ h) h2 (update-nth h (cons f l) g) variables))))) + + + (local + (defthm make-shared-variables-update-nth-disjoint-variables + (implies + (and (natp h) (natp h1) (natp h2) (< h h1) (<= h1 h2)) + (equal + (cadr (make-shared-variables + h1 h2 (update-nth h x g) variables)) + (cadr (make-shared-variables h1 h2 g variables)))) + :hints (("Goal" :induct (make-shared-variables h1 h2 g variables)) + ("Subgoal *1/4.2" + :expand (make-shared-variables h1 h2 (update-nth h x g) variables)) + ("Subgoal *1/3.2" + :expand (make-shared-variables h1 h2 (update-nth h x g) variables)) + ("Subgoal *1/2.2" + :expand (make-shared-variables h1 h2 (update-nth h x g) variables))))) + + +;; The following deals with base case 1 of the induction proof of our +;; main goal. Note that the lemma is needed because in some cases +;; the definition of {\tt make-shared-variables} is not expanded. + + (local + (defthm make-shared-variables-one-position-one-variable + (implies (and (variable-p term) + (natp h)) + (equal (make-shared-variables + h (1+ h) (update-nth h (cons term t) g) variables) + (if (assoc term variables) + (list + (update-nth h (cdr (assoc term variables)) g) + variables) + (list (update-nth h (cons term t) g) + (cons (cons term h) variables))))))) + + + +;; And finally, the intended result, proved by induction on the +;; structure of @term@ + + (defthm term-as-dag-aux-in-two-steps + (let* ((res1 (term-as-dag-aux flg term g h variables)) + (g-ret1 (first res1)) + (var-ret1 (fourth res1)) + (res2 (term-as-dag-aux-ns flg term g h)) + (g-ret2 (first res2)) + (h-ret2 (second res2))) + (implies (and (natp h) + (term-p-aux flg term)) + (and (equal g-ret1 + (first (make-shared-variables h h-ret2 g-ret2 variables))) + (equal var-ret1 + (second (make-shared-variables h h-ret2 g-ret2 + variables))))))))) + + +;;; ============================================================================ +;;; +;;; 6) Sharing variables preserves {\tt dag-p} +;;; +;;; ============================================================================ + +;;; Our intention in this section is to prove a theorem that will allow +;;; us to conclude that after applying {\tt make-shared-variables} to +;;; the graph obtained by {\tt term-as-dag-aux-ns} we obtain a graph +;;; thta verifies the {\tt init-term-dag-p} property and, consequently, +;;; the {\tt dag-p} property. Since we have proved in section 3 that the +;;; graph obtained by {\tt term-as-dag-aux-ns} verifies {\tt tree-p} +;;; then the following theorem will be our final goal in this section: + + +; (defthm init-term-dag-p-make-shared-variables +; (implies (and (natp h1) (natp h2) (<= h1 h2) (<= h2 (len g)) +; (tree-p g) (variables-well-stored-p h1 g variables)) +; (init-term-dag-p +; (first (make-shared-variables h1 h2 g variables))))) + +;;; This theorem will be a particular case of a more general theorem +;;; that can be proved by induction. The function {\tt +;;; variables-well-stored-p} defines some kind of "invariant" during the +;;; proccess of making variables shared; it defines how the association +;;; list computed by {\tt make-shared-variables} is related to the "piece" +;;; of graph already processed. + +;;; ----------------------------------- +;;; +;;; 6.1) Definition of the invariant +;;; +;;; ----------------------------------- + + +;;; As we have said above, the following definition formalizes some kind +;;; of "invariant" during the proccess of making variables shared; it +;;; defines how the association list computed by {\tt +;;; make-shared-variables} is related to the "piece" of graph already +;;; processed. Intuitively, it establishes that the association list +;;; @variables@ binds the variable nodes of the graph @g@ to the index +;;; of the nodes of the graph where they appear, for all the nodes with +;;; index less than @h@. That is, if we have made variables shared in +;;; @g@ until index @h-1@ then {\tt ((variables-well-stored-p h g +;;; variables)} where @vraibles@ is the association list computed {\tt +;;; make-shared-variables} up to that moment. + +(local + (defun variables-well-stored-p (h g variables) + (cond ((zp h) (equal variables nil)) + ((term-dag-variable-p (1- h) g) + (and (equal (term-dag-symbol (1- h) g) (caar variables)) + (equal (cdar variables) (1- h)) + (variables-well-stored-p (1- h) g (cdr variables)))) + (t (variables-well-stored-p (1- h) g variables))))) + + +;;; Now we prove some properties about @variables-well-stored-p@. For +;;; example, if {\tt (variables-well-stored-p h1 g variables)}, then in +;;; the association list @variables@ the variables are bound to +;;; natural numbers strictly less than the index @h1@, and those numbers +;;; point to variable nodes in the graph. + +(local + (defthm variables-well-stored-p-integerp + (implies (and (variables-well-stored-p h1 g variables) + (assoc x variables)) + (integerp (cdr (assoc x variables)))) + :rule-classes :type-prescription)) + +(local + (defthm variables-well-stored-p-positive + (implies (and (variables-well-stored-p h1 g variables) + (assoc x variables)) + (<= 0 (cdr (assoc x variables)))) + :rule-classes :linear)) + + + +(local + (defthm variables-well-stored-p-index-less-than + (implies (and (variables-well-stored-p h1 g variables) + (natp h1) + (assoc x variables)) + (< (cdr (assoc x variables)) h1)) + :rule-classes :linear)) + + + +(local + (defthm variables-well-stored-p-index-stores-variables + (implies (and (variables-well-stored-p h1 g variables) + (natp h1) + (assoc x variables)) + (term-dag-variable-p (cdr (assoc x variables)) g)))) + + +;;; These two lemmas establish how updating affects to {\tt +;;; variables-well-stored-p}: + +(local + (defthm variales-well-stored-p-update-nth-above-the-index + (implies (and (natp h1) (natp h2) (<= h1 h2)) + (equal (variables-well-stored-p h1 (update-nth h2 x g) + variables) + (variables-well-stored-p h1 g variables))) + :hints (("Goal" :induct (variables-well-stored-p h1 g variables)) + ("Subgoal *1/5" + :expand + (variables-well-stored-p h1 (update-nth h2 x g) variables))))) + + +(local + (defthm variables-well-stored-p-update-nth-at-the-index + (implies (and (assoc (car (nth h1 g)) variables) + (natp h1) + (variables-well-stored-p h1 g variables)) + (variables-well-stored-p + (+ 1 h1) + (update-nth h1 + (cdr (assoc (car (nth h1 g)) variables)) + g) + variables)) + :hints (("Goal" :expand (variables-well-stored-p + (+ 1 h1) + (update-nth h1 + (cdr (assoc (car (nth h1 g)) variables)) + g) + variables))))) + + +;;; ----------------------------------- +;;; +;;; 6.2) Proving the invariant and the intended property +;;; +;;; ----------------------------------- + + +;;; The following sequence of events helps to prove the lemma {\tt +;;; init-term-dag-p-make-shared-variables-main-lemma}, which describes +;;; the main invariant related to the {\tt init-term-dag-p} property +;;; during the proccess. The goal theorem in this section will be a +;;; particular case of that lemma. + +(local + (encapsulate + () + + (local + (defthm init-term-dag-p-aux-append + (equal (init-term-dag-p-aux (append hs1 hs2) g) + (and (init-term-dag-p-aux hs1 g) + (init-term-dag-p-aux hs2 g))))) + + + +;; Needed for {\tt Subgoal *1/4.3} + + + + (local + (defthm property-element-tree-p-property-element-init-term-dag-p + (implies (property-element-tree-p h node) + (property-element-init-term-dag-p h node g)))) + + + (local + (in-theory (disable property-element-tree-p + property-element-init-term-dag-p))) + + + (local + (defthm init-term-dag-p-aux-property-element-tree-p-lemma + (implies (and (natp h1) (natp h0) (<= h0 h1) + (init-term-dag-p-aux (list-from-to h0 h1) g) + (property-element-tree-p h1 (nth h1 g))) + (init-term-dag-p-aux (append (list-from-to h0 h1) + (list-from-to h1 (1+ h1))) + g)))) + + (local + (defthm init-term-dag-p-aux-property-element-tree-p + (implies (and (natp h1) (natp h0) (<= h0 h1) + (init-term-dag-p-aux (list-from-to h0 h1) g) + (property-element-tree-p h1 (nth h1 g))) + (init-term-dag-p-aux (list-from-to h0 (1+ h1)) + g)) + :hints (("Goal" :use init-term-dag-p-aux-property-element-tree-p-lemma + :in-theory (disable list-from-to))))) + + + (local + (defthm tree-p-aux-implies-property-element-tree-p + (implies (and (natp h1) (natp h2) (< h1 h2) + (tree-p-aux (list-from-to h1 h2) g)) + (property-element-tree-p h1 (nth h1 g))))) + + (local + (defthm init-term-dag-p-aux-one-index-beyond + (implies (and (tree-p-aux (list-from-to h1 h2) g) + (natp h1) (natp h2) (< h1 h2) (natp h0) (<= h0 h1) + (init-term-dag-p-aux (list-from-to h0 h1) g)) + (init-term-dag-p-aux (list-from-to h0 (1+ h1)) g)) + :hints (("Goal" + :use init-term-dag-p-aux-property-element-tree-p)))) + +;; Needed for {\tt Subgoal *1/4.2} + + (local + (defthm variables-well-stored-p-variables-one-index-beyond + (implies (and (not (term-dag-variable-p h1 g)) + (variables-well-stored-p h1 g variables)) + (variables-well-stored-p (1+ h1) g variables)))) + + + +;; Needed for {\tt Subgoal *1/4.1} + + (local + (defthm tree-p-aux-one-index-less + (implies (and (natp h1) (natp h2) (< h1 h2) + (tree-p-aux (list-from-to h1 h2) g)) + (tree-p-aux (list-from-to (1+ h1) h2) g)))) + + +;; Needed for {\tt Subgoal *1/3.1} + + (local + (defthm variables-well-stored-p-one-step-beyond + (implies (and (natp h1) + (term-dag-variable-p h1 g) + (variables-well-stored-p h1 g variables)) + (variables-well-stored-p (1+ h1) g + (cons (cons (car (nth h1 g)) h1) + variables))))) + + +;; Needed for {\tt Subgoal *1/2.2'} + + (local + (defthm variables-well-stored-p-not-variable-if-stored + (implies (and (variables-well-stored-p h1 g variables) + (assoc (car (nth h1 g)) variables)) + (not (equal (cddr (assoc (car (nth h1 g)) variables)) + t))) + :hints (("Goal" :use (:instance variables-well-stored-p-integerp + (x (car (nth h1 g)))))))) + + +;; Needed for {\tt Subgoal *1/2.1} + + (local + (defthm variables-well-stored-p-property-element-init-term-dag-p-update-nth + (implies (and (variables-well-stored-p h1 g variables) + (natp h1) + (assoc (car (nth h1 g)) variables)) + (property-element-init-term-dag-p + h1 (cdr (assoc (car (nth h1 g)) variables)) + (update-nth h1 + (cdr (assoc (car (nth h1 g)) variables)) + g))) + :hints (("Goal" :in-theory (enable property-element-init-term-dag-p))))) + + (local + (defthm property-element-init-term-dag-p-update-nth + (implies (and (natp h0) (natp h2) (< h0 h2) + (property-element-init-term-dag-p h0 (nth h0 g) + g)) + (property-element-init-term-dag-p h0 (nth h0 g) + (update-nth h2 x g))) + :hints (("Goal" :in-theory (enable property-element-init-term-dag-p))))) + + + (local + (defthm init-term-dag-p-aux-list-from-to-update-nth + (implies (and (natp h0) (natp h1) (natp h2) (<= h0 h1) (<= h1 h2) + (init-term-dag-p-aux (list-from-to h0 h1) g)) + (init-term-dag-p-aux (list-from-to h0 h1) (update-nth h2 x g))))) + + + + (local + (defthm init-term-dag-p-aux-update-nth-one-index-beyond-almost + (implies (and (variables-well-stored-p h1 g variables) + (natp h1) (natp h0) (<= h0 h1) + (init-term-dag-p-aux (list-from-to h0 h1) g) + (equal (cdr (nth h1 g)) t) + (assoc (car (nth h1 g)) variables)) + (init-term-dag-p-aux (append (list-from-to h0 h1) + (list-from-to h1 (1+ h1))) + (update-nth h1 + (cdr (assoc (car (nth h1 g)) variables)) + g))) + :hints (("Goal" :in-theory (disable append-list-from-to))))) + + + + (local + (defthm init-term-dag-p-aux-update-nth-one-index-beyond + (implies (and (variables-well-stored-p h1 g variables) + (natp h1) (natp h0) (<= h0 h1) + (init-term-dag-p-aux (list-from-to h0 h1) g) + (equal (cdr (nth h1 g)) t) + (assoc (car (nth h1 g)) variables)) + (init-term-dag-p-aux (list-from-to h0 (+ 1 h1)) + (update-nth h1 + (cdr (assoc (car (nth h1 g)) variables)) + g))) + :hints (("Goal" :use init-term-dag-p-aux-update-nth-one-index-beyond-almost + :in-theory (disable list-from-to))))) + + +;; And finally the main lemma: + + (defthm init-term-dag-p-make-shared-variables-main-lemma + (implies (and (natp h1) (natp h2) (natp h0) + (<= h0 h1) (<= h1 h2) + (tree-p-aux (list-from-to h1 h2) g) + (init-term-dag-p-aux (list-from-to h0 h1) g) + (variables-well-stored-p h1 g variables)) + (init-term-dag-p-aux + (list-from-to h0 h2) + (first (make-shared-variables h1 h2 g variables)))) + :hints (("Goal" :induct (make-shared-variables h1 h2 g variables)))) + + +;; We now prove the theorem {\tt init-term-dag-p-make-shared-variables} +;; presented above, simply noting that when {\tt tree-p} is verified by +;; a graph, then it verifies {\tt tree-p-aux} for every range of natural +;; numbers: + + + (local (in-theory (disable property-element-tree-p))) + + (local + (defthm property-element-tree-p-natp-all-indices + (implies (and (tree-p g) + (local-nat-listp hs)) + (tree-p-aux hs g)))) + + + (local + (defthm nth-aux-make-shared-variables-beyond-the-limit + (implies (and (natp h1) (natp h2) (natp h3) (<= h2 h3)) + (equal (nth h3 (first (make-shared-variables h1 h2 g + variables))) + (nth h3 g))))) + + + + (local + (defthm tree-p-aux-make-shared-variables-beyond-the-limit + (implies (and (natp h1) (natp h2) (natp h3) + (<= h2 h3) (natp h4) + (tree-p-aux (list-from-to h3 h4) g)) + (tree-p-aux (list-from-to h3 h4) + (first (make-shared-variables h1 h2 g variables)))))) + + + (local + (defthm init-term-dag-p-make-shared-variables-bridge-lemma + (implies (and (natp h1) (natp h2) (<= h1 h2) + (tree-p g) (variables-well-stored-p h1 g variables)) + (init-term-dag-p-aux + (append (list-from-to 0 h2) + (list-from-to h2 + (len + (first + (make-shared-variables h1 h2 g variables))))) + (first + (make-shared-variables h1 h2 g variables)))) + :rule-classes nil)) + + + (local + (defthm len-update-nth-corollary + (implies + (and (natp h1) (natp h2) (< h1 h2) + (< h1 h2) (<= h2 (len g))) + (not (< (len (update-nth h1 x g)) h2))))) + + + (local + (defthm len-make-shared-variables-auxiliar-property + (implies (and (natp h1) (natp h2) (<= h1 h2) (<= h2 (len g))) + (<= h2 (len (first (make-shared-variables h1 h2 g + variables))))) + :rule-classes :linear)) + + +;; Finally, the intended property: + + (defthm init-term-dag-p-make-shared-variables + (implies (and (natp h1) (natp h2) (<= h1 h2) (<= h2 (len g)) + (tree-p g) (variables-well-stored-p h1 g variables)) + (init-term-dag-p + (first (make-shared-variables h1 h2 g variables)))) + :hints (("Goal" :use + init-term-dag-p-make-shared-variables-bridge-lemma + :in-theory (enable tree-p init-term-dag-p)))))) + +;;; Note that when @h1@ is @0@, then the condition {\tt +;;; (variables-well-stored-p 0 g nil)} trivially holds, so the above +;;; theorem trivially implies that whenever {\tt (tree-p g)} then the +;;; graph {\tt (first (make-shared-variables 0 (len g) g nil))} verifies +;;; the {\tt init-term-dag-p} property. + +;;; ============================================================================ +;;; +;;; 7) How making shared variables affects to the graph +;;; +;;; ============================================================================ + + +;;; In this section we prove that the variables of the graph obtained +;;; after making the variables of a graph to be shared are +;;; not duplicated. That is, our goal in this sectionis: + +; (defthm no-duplicatesp-make-shared-variables-particular-case +; (no-duplicatesp +; (list-of-term-dag-variables +; (first +; (make-shared-variables 0 (len g) g nil)))) + +;;; And also we show that making variables to be shared preserves the +;;; stored first--order terms. That is, the following theorem: + +; (defthm dag-as-term-make-shared-variables +; (implies (and +; (natp h1) (natp h2) (<= h1 h2) +; (dag-p g) +; (variables-well-stored-p h1 g variables) +; (dag-p (first (make-shared-variables h1 h2 g variables)))) +; (equal (dag-as-term +; flg h (first (make-shared-variables h1 h2 g +; variables))) +; (dag-as-term flg h g)))) + + +;;; The main lemma needed in this section is the lemma {\tt +;;; make-shared-variables-variables-main-lemma} below establishing the +;;; relation between the variables bound by the association list +;;; computed by {\tt make-shared-variables}, and the variables appearing +;;; in the graph computed by {\tt make-shared-variables}: + +(local + (encapsulate + () + + (defun nths-from-to (l h1 h2) + (declare (xargs :measure (nfix (- h2 h1)))) + (if (zp (- h2 h1)) + nil + (cons (nth h1 l) + (nths-from-to l (1+ h1) h2)))) + + + (defun my-subseq-list (l h1 h2) + (declare (xargs :measure (list* (cons 1 (1+ (nfix (- h2 h1)))) (nfix h1)))) + (cond ((zp (- h2 h1)) nil) + ((zp h1) (cons (car l) (my-subseq-list (cdr l) h1 (- h2 1)))) + (t (my-subseq-list (cdr l) (- h1 1) (- h2 1))))) + + + (local + (defthm update-nth-nths-from-to + (implies (and (natp h) (natp h1) (natp h2) (< h h1)) + (equal (nths-from-to (update-nth h x g) h1 h2) + (nths-from-to g h1 h2))))) + + (defun alist-to-acl2-numberp (a) + (if (endp a) + t + (and (acl2-numberp (cdar a)) + (alist-to-acl2-numberp (cdr a))))) + + (local + (defthm alist-to-indices-does-not-provide-dag-variables + (implies (and (alist-to-acl2-numberp a) + (assoc x a)) + (acl2-numberp (cdr (assoc x a)))) + :rule-classes :type-prescription)) + + (defthm make-shared-variables-variables-main-lemma + (implies (and (natp h1) + (natp h2) + (alist-to-acl2-numberp variables)) + (equal + (strip-cars + (second (make-shared-variables h1 h2 g variables))) + (revappend + (list-of-term-dag-variables + (nths-from-to + (first (make-shared-variables h1 h2 g variables)) + h1 h2)) + (strip-cars variables)))) + :hints (("Goal" :induct (make-shared-variables h1 h2 g variables)))))) + + +;;; As a particular case of this main lemma, the lemma {\tt +;;; make-shared-variables-variables} below establish the relation +;;; between the variables bound by the association list and the +;;; variables of the graph after making variables to be shared in {\em all} +;;; the graph. + +(local + (encapsulate + () + (local + (defthm equal-nths-from-to-my-subseq-list-lemma + (implies (and (natp h1) (natp h2) (< h1 h2)) + (equal (my-subseq-list l h1 h2) + (cons (nth h1 l) + (my-subseq-list l (+ 1 h1) h2)))))) + + (local + (defthm equal-nths-from-to-my-subseq-list + (implies (and (natp h1) (natp h2)) + (equal (nths-from-to l h1 h2) + (my-subseq-list l h1 h2))))) + + (local + (defthm my-subseq-list-particular-case + (equal (my-subseq-list l 0 (len l)) + (fix-true-list l)) + :rule-classes nil)) + + (local + (defthm nths-from-to-particular-case + (equal (nths-from-to l 0 (len l)) (fix-true-list l)))) + + (local + (defthm list-of-term-dag-variables-fix-true-list-l + (equal (list-of-term-dag-variables (fix-true-list l)) + (list-of-term-dag-variables l)))) + + (local + (defthm revappend-rev-list + (equal (revappend l ac) + (append (revlist l) ac)))) + + (local + (defthm len-update-nth-corollary-2 + (implies (and (natp h) (< h (len g))) + (equal (len (update-nth h x g)) (len g))))) + + (local + (defthm len-make-shared-variables-arithmetic-lemma + (implies (and (not (zp (- h2 h1))) + (natp h1) (natp h2) + (<= h1 h2) + (<= h2 x)) + (< h1 x)) + :rule-classes nil)) + + (local + (defthm len-make-shared-variables + (implies (and (natp h1) (natp h2) (<= h1 h2) (<= h2 (len g))) + (equal + (len (first (make-shared-variables h1 h2 g variables))) + (len g))) + :hints (("Subgoal *1/4" + :use (:instance len-make-shared-variables-arithmetic-lemma + (x (len g))))) + :rule-classes nil)) + + (local + (defthm make-shared-variables-variables + (equal + (revlist + (list-of-term-dag-variables + (first + (make-shared-variables 0 (len g) g nil)))) + (strip-cars + (second (make-shared-variables 0 (len g) g nil)))) + + :hints (("Goal" :use + ((:instance len-make-shared-variables + (h1 0) (h2 (len g)) (variables nil)) + (:instance my-subseq-list-particular-case + (l (car (make-shared-variables 0 (len g) g nil))))))))) + +;; Finally it is to show that the variables bound by the association +;; list are not duplicated, and consequently (using the previous lemmas) +;; we prove (theorem {\tt +;; no-duplicatesp-make-shared-variables-particular-case}) that the list +;; of variables of the graph after making variables to be shared are not +;; duplicated (that is, the main goal in this section): + + (local + (defthm member-strip-cars-assoc + (implies (alistp a) + (iff (member x (strip-cars a)) + (assoc x a))))) + + (local + (defthm no-duplicatesp-make-shared-variables + (implies (and (alistp variables) (no-duplicatesp (strip-cars variables))) + (no-duplicatesp + (strip-cars + (second + (make-shared-variables h1 h2 g variables))))))) + + (local + (defthm no-duplicatesp-make-shared-variables-particular-case-lemma + (no-duplicatesp + (revlist + (list-of-term-dag-variables + (first + (make-shared-variables 0 (len g) g nil))))) + :hints (("Goal" + :in-theory + (disable equal-nths-from-to-my-subseq-list + no-duplicatesp-revlist + make-shared-variables-variables-main-lemma))))) + + + (defthm no-duplicatesp-make-shared-variables-particular-case + (no-duplicatesp + (list-of-term-dag-variables + (first + (make-shared-variables 0 (len g) g nil)))) + :hints (("Goal" + :use + no-duplicatesp-make-shared-variables-particular-case-lemma + :in-theory (disable + no-duplicatesp-make-shared-variables-particular-case-lemma + make-shared-variables-variables)))) + + + + +;; {\bf We now prove the last piece of our strategy}, before assembling the +;; pieces to prove our main goals in this book. We show now that the +;; terms computed by the function {\tt dag-as-term} are preserved +;; after making variables to be shared. + + (local + (defthm variables-are-not-is + (implies (term-dag-variable-p h g) + (not (term-dag-is-p h g))))) + + (local + (defthm variables-well-stored-p-assoc + (implies (and (assoc x variables) + (variables-well-stored-p h g variables)) + (equal (car (nth (cdr (assoc x variables)) g)) + x)))) + + (local + (defthm car-update-nth-in-strictly-positives-indices + (implies (and (integerp h) (< 0 h)) + (equal (car (update-nth h x g)) (car g))))) + + +;; Attention! The proof of the following lemma is very long, but I +;; prefer not to impose condition on @h@, since in that case I have to +;; impose conditions on @g@ and @gms@. + + + (local + (defthm make-shared-variables-dag-as-term-lemma + (let* ((c1 (nth h g)) + (gms (first (make-shared-variables h1 h2 g variables))) + (c2 (nth h gms))) + (implies (and + (natp h1) (natp h2) (<= h1 h2) + (not (equal c1 c2)) + (variables-well-stored-p h1 g variables) + (term-dag-variable-p h g)) + (and (integerp c2) + (term-dag-variable-p c2 gms) + (equal (term-dag-symbol c2 gms) + (term-dag-symbol h g))))) + :hints (("Goal" :induct (make-shared-variables h1 h2 g variables))))) + + + + (local + (defthm make-shared-variables-dag-as-term + (implies (and + (natp h1) (natp h2) (<= h1 h2) + (dag-p (first (make-shared-variables h1 h2 g variables))) + flg + (variables-well-stored-p h1 g variables) + (term-dag-variable-p h g)) + (equal (dag-as-term flg h + (first (make-shared-variables h1 h2 g + variables))) + (car (nth h g)))) + :hints + (("Goal" + :cases + ((equal (nth h g) + (nth h (first (make-shared-variables h1 h2 g variables))))))))) + + +;; And finally one of the intended theorems in this section, showing that {\tt +;; make-shared-variables} preserves the value of {\tt dag-as-term}. + + (defthm dag-as-term-make-shared-variables + (implies (and + (natp h1) (natp h2) (<= h1 h2) + (dag-p g) + (variables-well-stored-p h1 g variables) + (dag-p (first (make-shared-variables h1 h2 g variables)))) + (equal (dag-as-term + flg h (first (make-shared-variables h1 h2 g + variables))) + (dag-as-term flg h g))) + :hints (("Goal" :induct (dag-as-term flg h g)))))) + + +;;; ============================================================================ +;;; +;;; 9) Assembling all the pieces +;;; +;;; ============================================================================ + +;;; Recall that our goal is to prove the main properties of the graph +;;; computed by {\tt term-as-dag}, those properties that allows us to +;;; apply our unification algorithm acting on term dags to that +;;; graph. That is, under certain initial conditions, the following +;;; properties hold: + +;;; *) +;;; The graph is a well--formed directed acyclic graph +;;; *) +;;; The graph has no duplicates variables +;;; *) +;;; The term stored in the graph (at index 0) is the input term +;;; -) + +;;; This is the initial conditions we will assume about the graph {\em +;;; before} storing the graph. We simply assume that all the nodes are empty: + +(defun empty-graph-p (g) + (declare (xargs :guard t)) + (if (atom g) +; (equal g nil) + t + (and (not (car g)) + (empty-graph-p (cdr g))))) + +;;;---------------------------------------------------------------------------- +;;; +;;; 9.2) Properties +;;; +;;;---------------------------------------------------------------------------- + +(local + (defthm empty-graph-p-main-property + (implies (and (not (equal x nil)) + (member x g)) + (not (empty-graph-p g))))) + +(local + (defthm empty-graph-p-nth-main-property + (implies (not (equal (nth h g) nil)) + (not (empty-graph-p g))))) + +(defthm empty-graph-p-bounded-term-graph-p + (implies (empty-graph-p g) + (bounded-term-graph-p g n))) + +(defthm empty-graph-p-resize-list + (implies (empty-graph-p g) + (empty-graph-p (resize-list g size nil)))) + +;;; In particular, the intended result: + +(defthm empty-graph-p-implies-term-graph-p + (implies (empty-graph-p g) + (term-graph-p g)) + :rule-classes nil) + +;;; This condition trivially implies {\tt tree-p}: + +(local + (defthm empty-graph-p-property-element-tree-p + (implies (and (empty-graph-p g) + (or (member node g) + (equal node nil))) + (property-element-tree-p h node)))) + +(local + (defthm empty-graph-p-property-element-tree-p-nth + (implies (empty-graph-p g) + (property-element-tree-p h (nth h g))) + :hints (("Goal" :use (:instance empty-graph-p-property-element-tree-p + (node (nth h g))))))) + +(defthm member-nth-property + (implies (not (equal (nth h g) nil)) + (member (nth h g) g))) + +(local + (defthm empty-graph-p-tree-p-aux + (implies (empty-graph-p g) + (tree-p-aux hs g)) + :hints (("Goal" :in-theory (disable property-element-tree-p))))) + +(local + (defthm empty-graph-p-tree-p + (implies (empty-graph-p g) + (tree-p g)) + :hints (("Goal" :in-theory (enable tree-p))))) + +;;; The graph obtained by {\tt term-as-dag} verifies {\tt +;;; init-term-dag-p}: + +(local + (defthm term-as-dag-init-term-dag-p + (implies (and (tree-p g) (term-p term)) + (init-term-dag-p (term-as-dag term g))))) + +;;; The graph obtained by {\tt term-as-dag} is a directed acyclic graph + +(defthm term-as-dag-dag-p + (implies (and (empty-graph-p g) (term-p term)) + (dag-p (term-as-dag term g)))) + +;;; The graph obtained by {\tt term-as-dag} stores the input term (at +;;; index 0): + +(defthm term-as-dag-stores-term + (implies (and (empty-graph-p g) (term-p term)) + (equal (dag-as-term t 0 (term-as-dag term g)) + term))) + +;;; And the following sequence of events shows that the list of +;;; variables of the graph obtained by {\tt term-as-dag} has no +;;; duplicates (theorem {\tt term-as-dag-no-duplicatesp-variables} +;;; below): + +(encapsulate + () + + (local + (defun empty-graph-p-aux (hs g) + (declare (xargs :guard (and (nat-true-listp hs) (true-listp g)))) + (if (endp hs) + t + (and (equal (nth (car hs) g) nil) + (empty-graph-p-aux (cdr hs) g))))) + + (local + (defthm empty-graph-p-empty-graph-p-aux + (implies (empty-graph-p g) + (empty-graph-p-aux hs g)))) + + (local + (defthm make-shared-variables-empty-graph-p-aux-1 + (implies (and (natp h2) (natp h3) + (<= h2 h3) + (empty-graph-p-aux (list-from-to h2 h3) g)) + (equal (first (make-shared-variables h2 h3 g variables)) + g)))) + + (local + (defthm make-shared-variables-empty-graph-p-aux-2 + (implies (and (natp h1) (natp h2) (natp h3) (natp h4) + (<= h1 h2) (<= h2 h3) (<= h3 h4) + (empty-graph-p-aux (list-from-to h3 h4) g)) + (empty-graph-p-aux + (list-from-to h3 h4) + (first (make-shared-variables h1 h2 g variables)))))) + + (local + (defthm make-shared-variables-empty-graph-p-aux-final-segment + (implies (and (natp h1) (natp h2) (natp h3) + (<= h1 h2) (<= h2 h3) + (empty-graph-p-aux (list-from-to h2 h3) g)) + (equal (first (make-shared-variables h1 h3 g variables)) + (first (make-shared-variables h1 h2 g variables)))) + :hints (("Goal" :use make-shared-composition)))) + + (local + (defthm empty-graph-p-aux-term-as-dag-final-segment + (implies (and (empty-graph-p-aux hs g) + (natp h) + (subsetp hs + (list-from-to + (cadr (term-as-dag-aux-ns flg term g h)) + (len (car (term-as-dag-aux-ns flg term g h)))))) + (empty-graph-p-aux + hs (car (term-as-dag-aux-ns flg term g h)))) + :hints (("Goal" :induct (empty-graph-p-aux hs g))))) + + (defthm term-as-dag-no-duplicatesp-variables + (implies (and (empty-graph-p g) (term-p term)) + (no-duplicatesp + (list-of-term-dag-variables (term-as-dag term g)))) + :hints (("Goal" :use + (:instance make-shared-variables-empty-graph-p-aux-final-segment + (h1 0) (h2 (second (term-as-dag-aux-ns t term g 0))) + (h3 (len (first (term-as-dag-aux-ns t term g 0)))) + (g (first (term-as-dag-aux-ns t term g 0))) + (variables nil)) + :in-theory + (disable make-shared-variables-empty-graph-p-aux-final-segment)))) + + ) + +(local (in-theory (disable tree-p term-as-dag-aux-in-two-steps))) + +;;; ============================================================================ +;;; +;;; 10) The {\tt term-graph-p} property of {\tt term-as-dag-aux} +;;; +;;; ============================================================================ + + +;;; We have left (intentionally) one property about {\tt +;;; term-as-dag}. We show in this section that the graph obtained by +;;; {\tt term-as-dag } acting on an empty graph is a well formed term +;;; graph. + +;;; Unlike, the above properties, we will reason directly with the +;;; definition of {\tt term-as-dag-aux}. First, we prove that the +;;; property {\tt term-graph-p} is preserved by {\tt +;;; term-as-dag-aux}. And second, we show that {\tt empty-graph-p} +;;; implies {\tt term-graph-p}. + +;;; ----------------------------------- +;;; +;;; 10.1) The property {\tt term-graph-p} is preserved by {\tt term-as-dag-aux} +;;; +;;; ----------------------------------- + + +;;; The following propeerties show how some updates to graph does not +;;; change the {\tt bounded-term-graph-p} property. + +(local + (defthm bounded-term-graph-p-update-nth-args + (implies (and + (bounded-term-graph-p g n) + (eqlablep x) + (bounded-nat-true-listp l n)) + (bounded-term-graph-p (update-nth h (cons x l) g) n)))) + + +(local + (defthm bounded-term-graph-p-update-nth-variable + (implies (and + (bounded-term-graph-p g n) + (eqlablep x)) + (bounded-term-graph-p (update-nth h (cons x t) g) n)))) + + +(local + (defthm bounded-nat-substitution-p-assoc + (implies (and + (bounded-nat-substitution-p a n) + (assoc x a)) + (and (integerp (cdr (assoc x a))) + (< (cdr (assoc x a)) n) + (<= 0 (cdr (assoc x a))))))) + + + +(local + (defthm bounded-term-graph-p-update-nth-integer + (implies (and + (bounded-term-graph-p g n) + (natp x) (< x n)) + (bounded-term-graph-p (update-nth h x g) n)))) + + +;;; The main result of this subsection. Note that we prove an +;;; invariant of {\tt term-as-dag-aux}: + + +(defthm term-as-dag-aux-term-graph-p + (let* ((res (term-as-dag-aux flg term g h variables)) + (g-res (first res)) + (h-res (second res)) + (hs-res (third res)) + (var-res (fourth res))) + (implies (and (term-graph-p g) + (natp h) + (<= (+ h (length-term flg term)) (len g)) + (bounded-nat-substitution-p variables (len g)) + (term-p-aux flg term)) + (and (term-graph-p g-res) + (equal h-res (+ h (length-term flg term))) + (equal (len g-res) (len g)) + (bounded-nat-true-listp hs-res (len g)) + (bounded-nat-substitution-p var-res (len g)))))) + +;;; And the intended result of this subsection, a particular case of the +;;; above theorem: + +(defthm term-as-dag-term-graph-p + (implies (and (term-graph-p g) + (term-p term) + (<= (length-term t term) (len g))) + (term-graph-p (term-as-dag term g)))) + + +(in-theory (disable term-as-dag)) + +;;; ============================================================================ +;;; +;;; 11) Building unification problems +;;; +;;; ============================================================================ + +;;; The function {\tt terms-as-dag-l} will be our main auxiliary +;;; function for building (dag) unification problems. Recall that a +;;; unification problem (see {\tt dags.lisp}) is determined by an +;;; indices system, an indices substitution and a well--formed directed +;;; acyclic graph. Initially, the indices substitution is empty. We now +;;; describe how we build the graph and the indices system for a +;;; unification problem of the form $\{t_1=t_2\}$: + +;;; This function computes the graph. Note that the list that represents +;;; the graph is previously resized after computing how many nodes are +;;; needed. Also note that the term {\tt (equ t1 t2)} is stored in the +;;; graph using {\tt term-as-dag}: + +(defun unif-two-terms-problem (t1 t2 g) + (let* ((size (+ (length-term t t1) (length-term t t2) 1)) + (g (resize-list g size nil))) + (term-as-dag (list 'equ t1 t2) g))) + +;;; The initial indices system is taken from the argument list of the +;;; first node: + +(defun initial-to-be-solved (g) + (let ((args-0 (cdr (dagi-l 0 g)))) + (list (cons (first args-0) + (second args-0))))) + +;;; Following the results proved in the book {\tt +;;; dag-unification-rules}, our goal is to prove the following: + +; If (empty-graph-p g) +; let* g-t1-t2 = (unif-two-terms-problem t1 t2 g) +; S-dag-t1-t2 = (initial-to-be-solved g-t1-t2) +; then: +; (well-formed-dag-system S-dag-t1-t2 g-t1-t2) +; and +; (equal (tbs-as-system S-dag-t1-t2 g-t1-t2) +; (list (cons t1 t2))) + + +;;; If we prove the above property, we will able to use the theorems +;;; proved in {\tt dag-unification-rules} to conclude the properties of +;;; a unification algorithm that applies the rules of transformation +;;; starting with the above initial unification problem. + +;;; Resize list and {\tt length} + +(local + (defthm len-resize-list + (implies (natp n) + (equal (len (resize-list l n x)) n)))) + +(local (in-theory (disable resize-list))) + + +;;; The following sequence of events show that the initial unification +;;; problem built by the function {\tt unif-two-terms-problem} and +;;; {\tt initial-to-be-solved} is a well--formed directed acyclic +;;; graph. + + +;;; Luego lo meto dentro + +(defthm bounded-term-graph-p-particular-case + (implies (and (consp g) (term-graph-p g)) + (and (< (cadar g) (len g)) + (< (caddar g) (len g))))) + +(defthm consp-term-as-dag + (implies (consp g) + (consp (term-as-dag term g ))) + :hints (("Goal" :in-theory (enable term-as-dag)))) + + + +(defthm consp-resize-list + (implies (and (natp n) (< 0 n)) + (consp (resize-list l n x))) + :hints (("Goal" :in-theory (enable resize-list)) + ("Subgoal *1/2''" :expand (RESIZE-LIST L 1 X)))) + + + +(encapsulate + + () + + (local + (defthm equal-nth-car + (equal (nth 0 g) (car g)))) + + (local + (defthm len-args-term-as-dag-aux + (equal (len (third (term-as-dag-aux nil args g h variables))) + (len args)))) + + (local + (defthm term-as-dag-aux-first-element-len + (equal + (len + (cdr + (car + (first + (term-as-dag-aux t (cons symb args) g 0 nil))))) + (len args)))) + + (local + (defthm term-as-dag-first-element + (equal + (len + (cdr + (car + (term-as-dag (list 'equ t1 t2) g)))) + 2) + :hints (("Goal" :in-theory (enable term-as-dag))))) + +;;; Este me hace falta despues + (defthm term-as-dag-first-element-nth + (equal + (len + (cdr + (nth 0 + (term-as-dag (list 'equ t1 t2) g)))) + 2) + :hints (("Goal" :in-theory (enable term-as-dag)))) + + (local + (defthm nat-true-listp-len-two-first + (implies (and (nat-true-listp l) + (equal (len l) 2)) + (and (integerp (first l)) + (<= 0 (first l)))))) + + (local + (defthm nat-true-listp-len-two-second + (implies (and (nat-true-listp l) + (equal (len l) 2)) + (and (integerp (second l)) + (<= 0 (second l)))))) + (local + (defthm term-graph-p-first-element-nat-true-listp + (implies (and (equal (len (cdr (car g))) 2) + (term-graph-p g)) + (nat-true-listp (cdr (car g)))))) + + (defthm unif-two-terms-problem-well-formed-dag-system + (let* ((g-t1-t2 (unif-two-terms-problem t1 t2 g)) + (S-dag-t1-t2 (initial-to-be-solved g-t1-t2))) + (implies (and (empty-graph-p g) (term-p t1) (term-p t2)) + (well-formed-dag-system S-dag-t1-t2 g-t1-t2))) + :hints (("Goal" + :use + (:instance term-as-dag-term-graph-p + (g (resize-list g (+ (length-term t t1) (length-term t t2) + 1) nil)) + (term (list 'equ t1 t2)))) + ("Subgoal 1" :in-theory (enable + well-formed-upl))))) + + + +;;; And finally, the following sequence of events show that the initial +;;; unification problem built by the function {\tt +;;; unif-two-terms-problem} and {\tt initial-to-be-solved} stores +;;; (in a dag form) the initial unification problem: + + +(encapsulate + () + + (local + + (defthm unif-two-terms-problem-stores-the-problem-lemma-1 + (implies (and + (equal (len (cdr (nth h g))) 2) + (equal (dag-as-term t h g) + (list 'equ t1 t2))) + (equal (dag-as-term t (first (cdr (nth h g))) g) + t1)) + :hints (("Subgoal 1'" :expand (dag-as-term nil (cdr (nth h g)) g))))) + + + + (local + (defthm unif-two-terms-problem-stores-the-problem-lemma-2 + (implies (and + (equal (len (cdr (nth h g))) 2) + (equal (dag-as-term t h g) + (list 'equ t1 t2))) + (equal (dag-as-term t (second (cdr (nth h g))) g) + t2)) + :hints (("Goal'''" :expand (dag-as-term nil (cdr (nth h g)) g)) + ("Goal'5'" :expand (dag-as-term nil (cddr (nth h g)) g))))) + + (local + (defthm unif-two-terms-problem-stores-the-problem-almost + (let* ((g-t1-t2 (unif-two-terms-problem t1 t2 g)) + (S-dag-t1-t2 (initial-to-be-solved g-t1-t2))) + (implies (and (empty-graph-p g) (term-p t1) (term-p t2) + (equal (dag-as-term t 0 g-t1-t2) + (list 'equ t1 t2))) + (equal (tbs-as-system S-dag-t1-t2 g-t1-t2) + (list (cons t1 t2))))) + :hints (("Goal" :in-theory + (disable nth term-as-dag-stores-term))) + :rule-classes nil)) + + + (defthm unif-two-terms-problem-stores-the-problem + (let* ((g-t1-t2 (unif-two-terms-problem t1 t2 g)) + (S-dag-t1-t2 (initial-to-be-solved g-t1-t2))) + (implies (and (empty-graph-p g) (term-p t1) (term-p t2)) + (equal (tbs-as-system S-dag-t1-t2 g-t1-t2) + (list (cons t1 t2))))) + :hints (("Goal" :use unif-two-terms-problem-stores-the-problem-almost)))) + + + + +;;; =============================================================== |