• Top
    • Documentation
    • Books
    • Recursion-and-induction
    • Boolean-reasoning
    • Projects
    • Debugging
    • Std
    • Proof-automation
      • Gl
      • Witness-cp
        • Definstantiate
        • Defexample
        • Defwitness
        • Defquantexpr
        • Def-witness-ruleset
        • Witness
        • Defquant
      • 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
  • Proof-automation

Witness-cp

Clause processor for quantifier-based reasoning.

Signature
(witness-cp clause hint state) → (mv err new-clause)
Arguments
clause — Guard (pseudo-term-listp clause).
Returns
new-clause — Type (pseudo-term-list-listp new-clause), given (pseudo-term-listp clause).

Introduction

Witness-cp is an extensible clause-processor that can apply user-supplied rules to carry out witnessing transformations on quantifier-like terms in ACL2 proof goals.

Witness-cp is a general purpose tool that you can configure to work with any kinds of quantifiers. As a familiar example, consider set reasoning. If we encounter some proof goal with a hypothesis of the form:

(subsetp-equal x y)

then we may want to use this hypothesis to draw specific conclusions, such as:

(implies (member-equal k x)
         (member-equal k y))

for various k. Similarly if we have a hypothesis of the form:

(not (subsetp-equal y z))

then we may wish to conclude facts such as:

(and (member-equal j y)
     (not (member-equal j z)))

for various j. Many theorems in set theory can be proven by choosing suitable j and k and then carrying out membership reasoning. The witness-cp clause processor can be configured to automatically try such j and k in reasonably smart ways.

More broadly, witness-cp is a general purpose tool that can configured to reason about arbitrary quantified formulas. It knows nothing a priori about set theory or any other domain, but it can be told about what predicates are to be taken as universal/existential quantifiers and how they should be instantiated.

Usage

There are two steps to using witness-cp. First, we must configure it to understand the desired domain, e.g., for set theory, we would need to explain that subsetp-equal is the universal quantification of member-equal. Once the domain is configured, we can instruct ACL2 to apply the witness-cp clause processor to particular goals that we want to solve; this is typically done with an explicit witness hint or via default-hints.

At a high level, when witness-cp transforms a proof goal, it carries out the following steps, each of which need to be configured to understand your domain:

  1. Witnessing. Introduce witnesses for negative occurrences of universally quantified predicates and positive occurrences of existentially quantified ones. Then, optionally, for better readability, generalize the newly introduced witness terms into fresh variables. These steps can be controlled with defwitness.
  2. Gathering. Find the set of examples with which to instantiate positive universally quantified and negative existentially quantified predicates. The predicates to target are controlled by definstantiate.
  3. Instantiation. Instantiate these predicates with these examples. The examples are set up using defexample.

Note that witness introduction and instantiation may both be lossy, i.e., they may result in a formula that isn't a theorem even if the original formula is one!

Extended Example: Set Theory

We now run through a typical example of setting up witness-cp to understand some functions from set theory.

Configuring Witnessing

To set up witnessing for (not (subsetp-equal a b)) hypotheses, we can issue the following defwitness event. We assume here that (subsetp-equal-witness a b) is a suitable ``badguy'' function that finds a member of a that is not in b, if one exists.

(defwitness subsetp-witnessing
  :predicate (not (subsetp-equal a b))
  :expr (and (member-equal (subsetp-equal-witness a b) a)
             (not (member-equal (subsetp-equal-witness a b) b)))
  :generalize (((subsetp-equal-witness a b) . ssew))
  :hints ('(:in-theory '(subsetp-equal-witness-correct))))

This instructs witness-cp, during the witnessing phase, to search for hypotheses of the form (not (subsetp-equal a b)). For any such matches, witness-cp will add the new hypothesis:

(and (member-equal (subsetp-equal-witness a b) a)
     (not (member-equal (subsetp-equal-witness a b) b)))

and will then generalize away the term (subsetp-equal-witness a b) to a fresh variable with a name like SSEW0, SSEW1, etc. After this generalization we are left with two new hyps:

(member-equal ssew0 a)
(not (member-equal ssew0 b))

The net result of all of this is that we have replaced an existential assumption with a fresh variable witnessing it. We wrap (hide ...) around the original hypothesis to leave a trace of what we've done. (Otherwise, it would likely be rewritten away, since the two new hyps imply it.)

Why is it sound to add these new hypotheses to our main formula? To justify this step, the defwitness event requires us to prove the following theorem, using the provided hints:

(implies (not (subsetp-equal a b))
         (and (member-equal (subsetp-equal-witness a b) a)
              (not (member-equal (subsetp-equal-witness a b) b))))
Configuring Gathering

To set up instantiation of a (subsetp-equal a b) hypotheses, we can issue the following definstantiate event.

(definstantiate subsetp-equal-instancing
  :predicate (subsetp-equal a b)
  :vars (k)
  :expr (implies (member-equal k a)
                 (member-equal k b))
  :hints ('(:in-theory '(subsetp-member))))

This will mean that, for each (subsetp-equal a b) hypothesis we find, we'll add hypotheses of the form:

(implies (member-equal k a)
         (member-equal k b))

for each of (possibly) several k. The terms we use to instantiate k are determined by defexample; see below.

To show that it sound to add these hypotheses, the definstantiate event requires us to prove:

(implies (subsetp-equal a b)
         (implies (member-equal k a)
                  (member-equal k b)))

This is a very easy proof: it is just the quantifier-based definition of subsetp-equal.

Configuring Instantiation

The terms used to instantiate k above are determined by defexample rules, like the following:

(defexample subsetp-member-template
  :pattern (member-equal k a)
  :templates (k)
  :instance-rulename subsetp-equal-instancing)

This rule means that, after the gathering phase, we'll look through the clause for expressions (member-equal k a) and, whenever we find one, include k in the list of examples to use for instantiating using the subsetp-equal-instance rule.

Defexample doesn't require any proof obligation; it's just a heuristic that adds to the set of terms used to instantiate universal quantifiers.

Applying the Clause Processor

To use the scheme we've introduced for reasoning about subsetp-equal, we can introduce a witness ruleset:

(def-witness-ruleset subsetp-witnessing-rules
  '(subsetp-witnessing
    subsetp-equal-instancing
    subsetp-member-template))

Then when we want to use this reasoning strategy, we can give a hint. You should not call witness-cp directly, but rather using the witness macro as a computed hint. For example:

:hints ((witness :ruleset subsetp-witnessing-rules))

This implicitly waits until the formula is stable-under-simplificationp and then invokes the witness-cp clause processor, allowing it to use the witnessing/instancing/example rules listed.

You may find it useful to define a macro so that you don't have to remember this syntax, for instance:

(defmacro subset-reasoning ()
  '(witness :ruleset subsetp-witnessing-rules))

(defthm foo
  ...
  :hints (("goal" ...)
          (subset-reasoning)))

Further Resources

Additional documentation is available for defwitness, definstantiate, and defexample. Also see defquantexpr, which is a shortcut for the common pattern (as above) of doing both a defwitness and definstantiate for a certain term, and defquant, which defines a quantified function (using defun-sk) and sets up defwitness/definstantiate rules for it.

Subtopics

Definstantiate
Add a witness-cp rule showing how to instantiate a universal quantifier hypothesis (or an existential quantifier conclusion).
Defexample
Tell witness-cp how to instantiate the free variables of definstantiate rules.
Defwitness
Add a witness-cp rule providing a witness for an existential quantifier hypothesis (or universal quantifier conclusion).
Defquantexpr
Shortcut to perform both a defwitness and definstantiate.
Def-witness-ruleset
Name a set of witness-cp rules.
Witness
Computed hint for calling the witness-cp clause processor.
Defquant
Define a quantified function and corresponding witness-cp rules.