ACCUMULATED-PERSISTENCE-SUBTLETIES.html -- ACL2 Version 6.3

### ACCUMULATED-PERSISTENCE-SUBTLETIES

some subtle aspects of the counting done by `accumulated-persistence`

    Major Section:  ACCUMULATED-PERSISTENCE

In this topic we cover the overcounting of ``useful'' and of recursive rune application attempts, and we describe how ``useless'' rune application attempts can actually be critical for a proof's success.

Overcounting of ``useful'' and of recursive rune application attempts. Not every rune application may be necessary for a proof's success. Consider for example:

    (thm (equal (car (cons a (cdr (cons b x))))
                a))

Then `show-accumulated-persistence` will tell us that `:``rewrite` rules `car-cons` and `cdr-cons` each had one useful application. However, the rule `cdr-cons` is used to simplify `(cdr (cons b x))` to `x`, and this simplification is unecessary for the proof. Indeed, the proof succeeds even when preceded by the event: `(in-theory (disable cdr-cons))`. We thus see that a rune application labeled as ``useful'' may be simplifying a term that is not relevant to the proof.

As of this writing, we consider every `:``forward-chaining` rule application to be ``useful'', for simplicity of the implementation. Moreover, our counting of these rules is such that a single rule may be counted more than once.

Next we show how recursive rule applications are overcounted. Consider the following example.

    (defun mem (a x)
      (if (atom x)
          nil
        (or (equal a (car x)) (mem a (cdr x)))))

Now suppose we consider the sequence of theorems `(mem a (list a))`, `(mem a (list 1 a))`, `(mem a (list 1 2 a))`, `(mem a (list 1 2 3 a))`, and so on. We will see that the `:frames` reported for each increases quadratically, even though the `:tries` increases linearly; so in this case the `:tries` statistics are more appropriate. Each time the definition of `mem` is applied, a new stack frame is pushed (see accumulated-persistence), and all subsequent applications of that definition are accumulated into the `:frames` count for that stack frame. The final `:frames` count will be the sum of the counts for those individual frames, which form a linear sequence whose sum is therefore quadratic in the number of applications of the definition of `mem`.

How ``useless'' attempts can be critical for a proof's success. The command `(accumulated-persistence :useless`)] will list rules that did not contribute directly to the proof (see accumulated-persistence, in particular the discussion of ``useless'' there). However, a ``useless'' rule can on rare occasions be critical to the success of a proof. In the following example, we have a ``bad'' rule that can take the proof in the wrong direction, but a ``useless'' rule does a rewrite that prevents the succesful relieving of a hypothesis of the ``bad'' rule. In summary:

    ; Assume p0.  We want to prove p1.

    ; Key rule:
    p0 -> p1 = t

    ; Bad rule that could ruin the proof:
    p3 -> p1 = p2

    ; But unfortunately, we know p3:
    p0 -> p3

    ; Important ``useless'' rule, preventing ``bad rule'' above from firing:
    p3 = p4

The following event captures the rules described above.

    (encapsulate
     ((p0 (x) t)
      (p1 (x) t)
      (p2 (x) t)
      (p3 (x) t)
      (p4 (x) t))
     (local (defun p0 (x) x))
     (local (defun p1 (x) x))
     (local (defun p2 (x) x))
     (local (defun p3 (x) x))
     (local (defun p4 (x) x))

    ; Key rule:
     (defthm p0-implies-p1
       (implies (p0 x)
                (p1 x)))

    ; Bad rule that could ruin the proof:
     (defthm p3-implies-p1-is-p2
       (implies (p3 x)
                (equal (p1 x) (p2 x))))

    ; But unfortunately, we know p3:
     (defthm p0-implies-p3
       (implies (p0 x)
                (p3 x)))

    ; Important ``useless'' rule, preventing p3-implies-p1-is-p2 from firing:
     (defthm p3-is-p4
       (equal (p3 x) (p4 x))))

Now we can see that `p3-is-p4` is labeled as ``useless'', by evaluating these commands.

    (accumulated-persistence t)
    (thm (implies (p0 x) (p1 x)))
    (show-accumulated-persistence)

If instead we first evaluate `(in-theory (disable p3-is-p4))` before the `thm` above, then the proof fails, even though `p3-is-p4` was labeled as ``useless''!

Nevertheless, in general it is probably safe to disable rules reported as ``useless'' by `(show-accumulated-persistence :useless)`, and doing so may speed up a proof considerably.

Remark. The example above suggests a surprising fact: on rare occasions, a proof may fail when you give an `:``in-theory` hint consisting of exactly the runes reported in a proof that succeeds. For, imagine a rule R that is needed in part of the proof but is ``bad'' in a second part, and that some other, ``useless'' rule prevents the application of R in that second part. The example above suggests that disabling this ``useless'' rule can allow the second application of R, thus preventing the proof.