CONGRUENCE.html -- ACL2 Version 6.3

## CONGRUENCE

the relations to maintain while simplifying arguments

    Major Section:  RULE-CLASSES

See rule-classes for a general discussion of rule classes and how they are used to build rules from formulas. An example `:``corollary` formula from which a `:congruence` rule might be built is:

    Example:
    (defthm set-equal-implies-iff-memb-2
      (implies (set-equal x y)
               (iff (memb e x) (memb e y)))
      :rule-classes :congruence)

Also see defcong and see equivalence.

    General Form:
    (implies (equiv1 xk xk-equiv)
             (equiv2 (fn x1... xk       ...xn)
                     (fn x1... xk-equiv ...xn)))

where `equiv1` and `equiv2` are known equivalence relations, `fn` is an `n-ary` function symbol and the `xi` and `xk-equiv` are all distinct variables. The effect of such a rule is to record that the `equiv2`-equivalence of `fn`-expressions can be maintained if, while rewriting the `kth` argument position, `equiv1`-equivalence is maintained. See equivalence for a general discussion of the issues. We say that `equiv2`, above, is the ``outside equivalence'' in the rule and `equiv1` is the ``inside equivalence for the `k`th argument''

The macro form `(defcong equiv1 equiv2 (fn x1 ... x1) k)` is an abbreviation for a `defthm` of rule-class `:congruence` that attempts to establish that `equiv2` is maintained by maintaining `equiv1` in `fn`'s `k`th argument. The `defcong` macro automatically generates the general formula shown above. See defcong.

The `memb` example above tells us that `(memb e x)` is propositionally equivalent to `(memb e y)`, provided `x` and `y` are `set-equal`. The outside equivalence is `iff` and the inside equivalence for the second argument is `set-equal`. If we see a `memb` expression in a propositional context, e.g., as a literal of a clause or test of an `if` (but not, for example, as an argument to `cons`), we can rewrite its second argument maintaining `set-equality`. For example, a rule stating the commutativity of `append` (modulo set-equality) could be applied in this context. Since equality is a refinement of all equivalence relations, all equality rules are always available. See refinement.

All known `:congruence` rules about a given outside equivalence and `fn` can be used independently. That is, consider two `:congruence` rules with the same outside equivalence, `equiv`, and about the same function `fn`. Suppose one says that `equiv1` is the inside equivalence for the first argument and the other says `equiv2` is the inside equivalence for the second argument. Then `(fn a b)` is `equiv` `(fn a' b')` provided `a` is `equiv1` to `a'` and `b` is `equiv2` to `b'`. This is an easy consequence of the transitivity of `equiv`. It permits you to think independently about the inside equivalences.

Furthermore, it is possible that more than one inside equivalence for a given argument slot will maintain a given outside equivalence. For example, `(length a)` is equal to `(length a')` if `a` and `a'` are related either by `list-equal` or by `string-equal`. You may prove two (or more) `:congruence` rules for the same slot of a function. The result is that the system uses a new, ``generated'' equivalence relation for that slot with the result that rules of both (or all) kinds are available while rewriting.

`:Congruence` rules can be disabled. For example, if you have two different inside equivalences for a given argument position and you find that the `:``rewrite` rules for one are unexpectedly preventing the application of the desired rule, you can disable the rule that introduced the unwanted inside equivalence.

Remark on Replacing IFF by EQUAL. You may encounter a warning suggesting that a congruence rule ``can be strengthened by replacing the second equivalence relation, IFF, by EQUAL.'' Suppose for example that this warning occurs when you submit the following rule:

    (defcong equiv1 iff (fn x y) 2)

which is shorthand for the following:

    (defthm equiv1-implies-iff-fn-2
           (implies (equiv1 y y-equiv)
                    (iff (fn x y) (fn x y-equiv)))
           :rule-classes (:congruence))

The warning is telling you that ACL2 was able to deduce that `fn` always returns a Boolean, and hence a trivial but useful consequence is obtained by replacing `iff` by `equal` --

    (defcong equiv1 equal (fn x y) 2)

-- which is shorthand for the following:

    (defthm equiv1-implies-equal-fn-2
           (implies (equiv1 y y-equiv)
                    (equal (fn x y) (fn x y-equiv)))
           :rule-classes (:congruence))

If you have difficulty proving the latter directly, you can derive it from the former by giving a suitable hint, minimally as follows.

    (defcong equiv1 equal (fn x y) 2
      :hints (("Goal"
               :use equiv1-implies-iff-fn-2
               :in-theory
               (union-theories '((:type-prescription fn))
                               (theory 'minimal-theory)))))

By heeding this warning, you may avoid unnecessary `double-rewrite` warnings later. We now explain why, but see double-rewrite for relevant background material.

For example, suppose you have proved the ```iff`'' version of the congruence rule above, and later you submit the following rewrite rule.

    (defthm equal-list-perm
      (implies (equiv1 x y)
               (fn x y)))

Since `fn` is known to return a Boolean, ACL2 performs an optimization that stores this rule as though it were the following.

    (defthm equal-list-perm
      (implies (equiv1 x y)
               (equal (fn x y) t)))

Thus, if ACL2's rewriter sees a term `(fn a b)` in a context where the equivalence relation `iff` is not being maintained, then it cannot use rule `equiv1-implies-iff-fn-2`, so it rewrites argument `a` without the benefit of knowing that it suffices to maintain `equiv1`; and then it caches the result. When ACL2 subsequently attempts to relieve the hypothesis `(equiv1 x y)`, it will rewrite `x` simply by returning the rewritten value of `a` from the result cache. This is unfortunate if `a` could have been rewritten more completely under maintainance of the equivalence relation `equiv1` -- which is legal in the hypothesis since `a` is an argument of `equiv1`, which is an equivalence relation. The user who observes the warning from rule `equiv1-implies-iff-fn-2`, and replaces it with `equiv1-implies-equal-fn-2`, will avoid this unfortunate case.