• Top
    • Documentation
    • Books
    • Recursion-and-induction
    • Boolean-reasoning
    • Projects
    • Debugging
    • Std
    • Proof-automation
      • Gl
        • Term-level-reasoning
        • Glmc
        • Other-resources
        • Optimization
        • Reference
        • Debugging
          • False-counterexamples
          • Coverage-problems
            • Performance-problems
            • Memory-management
          • Basic-tutorial
        • Witness-cp
        • Ccg
        • Install-not-normalized
        • Rewrite$
        • Removable-runes
        • Efficiency
        • Rewrite-bounds
        • Bash
        • Def-dag-measure
        • Fgl
        • Bdd
        • Remove-hyps
        • Contextual-rewriting
        • Simp
        • Rewrite$-hyps
        • Bash-term-to-dnf
        • Use-trivial-ancestors-check
        • Minimal-runes
        • Clause-processor-tools
        • Fn-is-body
        • Without-subsumption
        • Rewrite-equiv-hint
        • Def-bounds
        • Rewrite$-context
        • Try-gl-concls
        • Hint-utils
      • Macro-libraries
      • ACL2
      • Interfacing-tools
      • Hardware-verification
      • Software-verification
      • Testing-utilities
      • Math
    • Debugging

    Coverage-problems

    Proving the coverage obligation in GL-based proofs.

    In order to prove a theorem using GL, one must show that the symbolic objects chosen to represent the inputs are sufficiently general to cover the entire set of interest. See shape-specs for a more in-depth discussion. The def-gl-thm and def-gl-param-thm events as well as the gl-hint hints all provide some degree of automation for coverage proofs; often this is enough to satisfy the coverage obligation without further user interaction. Here we discuss how to debug coverage proofs that do not succeed.

    First, it is probably important to be able to re-run a coverage proof easily without also re-running the associated symbolic execution, which may be quite time-consuming. To do this, in either the def-gl-thm or def-gl-param-thm forms, add the keyword argument :TEST-SIDE-GOALS T. This form will then try to prove the coverage obligation in exactly the manner it would do during the real proof, but it will not attempt to prove the theorem itself, and will not record a new ACL2 theorem even if the proof is successful.

    During proof output, GL prints a message "Now proving coverage" when it begins the coverage proof. The initial goal of a coverage proof will also have a hypothesis (GL::GL-CP-HINT 'GL::COVERAGE); this hypothesis is logically meaningless, but a useful indicator of the beginning of a coverage proof.

    When GL's usual set of heuristics is used, a coverage proof proceeds as follows. The initial goal is as follows:

    (implies <theorem-hyps>
             (gl::shape-spec-obj-in-range
               <list-of-input-bindings>
               <list-of-input-variables>))

    The coverage heuristics proceed by repeatedly opening up the GL::SHAPE-SPEC-OBJ-IN-RANGE function. This effectively splits the proof into cases for each component of each variable; for example, if one variable's shape specifier binding is a cons of two :G-INTEGER forms, then its CAR and CDR will be considered separately. Eventually, this results in several subgoals, each with conjunction of requirements for some component of some input.

    During this process of opening the GL::SHAPE-SPEC-OBJ-IN-RANGE conclusion, the coverage heuristics also examine and manipulate the hypotheses. When the conclusion is focused on a certain input variable or component of that variable, and some hypothesis does not mention that variable, that hypothesis will be dropped so as to speed up the proof. If a hypothesis does mention that variable, it may be expanded (if it is not a primitive) so as to try and gain more information about that variable. This is a useful heuristic because often the hypotheses consist of a conjunction of predicates about different input variables or components of input variables, and some of these predicates are often themselves defined as conjunctions of predicates about subcomponents.

    However, sometimes this expansion goes too far. In many cases, some conjuncts from the hypothesis have nothing to do with the coverage obligation. In these cases, the :DO-NOT-EXPAND keyword argument to DEF-GL-THM and DEF-GL-PARAM-THM may be used. This argument should evaluate to a list of function symbols; the coverage heuristic is then prohibited from expanding any of these functions.

    For efficiency, the set of rules used in coverage proofs is very restricted. Because of this, you may see in the proof output a goal which should be obvious, but is not proven because the necessary rule is not included. The keyword argument :COV-THEORY-ADD may be used to enable certain additional rules that are not included. The set of rules that are used is defined in the ruleset GL::SHAPE-SPEC-OBJ-IN-RANGE-OPEN, which can be listed using

    (get-ruleset 'gl::shape-spec-obj-in-range-open (w state)).

    The default heuristics for coverage proofs may not always be useful. Therefore, the user may also supplement or replace the coverage heuristics with arbitrary computed hints. The keyword argument :COV-HINTS gives a list of computed hint forms which, according to the value of the keyword argument :COV-HINTS-POSITION, either replaces or supplements the default hints. :COV-HINTS-POSITION may be either :REPLACE, in which case the defaults are not used at all; :FIRST, in which case the user-provided :COV-HINTS are tried first and the defaults afterward, or the default, :LAST, in which case the default coverage heuristic is tried before the user-provided hints.

    Note that subgoal names will be different between a :TEST-SIDE-GOALS and an actual attempt at proving the theorem. Therefore, it is best not to write computed hints that depend on the ID variable.