Search code examples
coqcoq-tactic

Coq auto tacitc fails


I have the following Coq program that tries to prove n <= 2^n with auto:

(***********)
(* imports *)
(***********)
Require Import Nat.

(************************)
(* exponential function *)
(************************)
Definition f (a : nat) : nat := 2^a.

Hint Resolve plus_n_O.
Hint Resolve plus_n_Sm.

(**********************)
(* inequality theorem *)
(**********************)
Theorem a_leq_pow_2_a: forall a, a <= f(a).
Proof.
  auto with *.
Qed.

I expected Coq to either succeed or get stuck trying to. But it immediately returns. What am I doing wrong?

EDIT I added the Hint Unfold f., and increased bound to 100 but I can't see any unfolding done with debug auto 100:

(* debug auto: *)
* assumption. (*fail*)
* intro. (*success*)
* assumption. (*fail*)
* intro. (*fail*)
* simple apply le_n (in core). (*fail*)
* simple apply le_S (in core). (*fail*)

EDIT 2 I'm adding the manual proof to demonstrate its complexity:

(**********************)
(* inequality theorem *)
(**********************)
Theorem a_leq_pow_2_a: forall a, a <= f(a).
Proof.
  induction a as[|a' IHa].
  - apply le_0_n.
  - unfold f.
    rewrite Nat.pow_succ_r.
    * rewrite Nat.mul_comm.
      rewrite Nat.mul_succ_r.
      rewrite Nat.mul_1_r.
      unfold f in IHa.
      rewrite Nat.add_le_mono with (n:=1) (m:=2^a') (p:=a') (q:=2^a').
      -- reflexivity.
      -- apply Nat.pow_le_mono_r with (a:=2) (b:=0) (c:=a').
         auto. apply le_0_n.
      -- apply IHa.
    * apply le_0_n.
Qed.

Solution

  • The manual proof that you performed explains why auto can't do it. You did a proof by induction and then a few rewrites. The auto tactic does not allow itself this kind of step.

    The tactic auto is meant to find a proof if a manual proof only uses apply with a restricted set of theorems. Here the restrict set of theorems is taken from the core hint database. For the sake of brevity, let's assume this database only contains le_S, le_n, plus_n_O and plus_n_Sm.

    To simplify, let's assume that we work with the goal a <= 2 ^ a. The head predicate of this statement is _ <= _ so the tactic will only look at theorems whose principal statement is expressed with _ <= _. This rules out plus_n_O and plus_n_Sm. Your initiative of adding these goes down the drain.

    If we look at le_n the statement is forall n : nat, n <= n. If we replace the universal quantification by a pattern variable, this pattern is ?1 < ?1. Does this unify with a <= 2 ^ a? The answer is no. so this theorem won't be used by auto. Now if we look at le_S, the pattern of the principal statement is ?1 <= S ?2. Unifying this pattern with a <= 2 ^ a, this would require ?1 to be a. Now what could be the value of ?2? We need to compare symbolically the expressions 2 ^ a and S ?2. On the left hand side the function symbol is either _ ^ _ or 2 ^ _ depending on how you wish to look at it, but anyway this is not S. So auto recognizes these functions are not the same, the lemma cannot apply. auto fails.

    I repeat: when given a goal, auto first only looks at the head symbol of the goal, and it selects from its database the theorems that achieves proofs for this head symbol. In your example, the head symbol is _ <= _. Then it looks only at the conclusion of these theorems, and checks whether the conclusion matches syntactically with the goal at hand. If it does match, then this should provide values for the universally quantified variables of the theorem, and the premises of the theorem are new goals that should be solved at a lower depth. As was mentioned by @Elazar, the depth is limited to 5 by default.

    The Hint unfold directive would be useful only if you had made a definition of the following shape:

    Definition myle (x y : nat) := x <= y.
    

    Then Hint Unfold myle : core. would be useful to make sure that the database theorems for _ <= _ are also used to proved instances of myle, as in the following example (it fails if we have 4 occurrences of S, because of the depth limitation).

    Lemma myle3 (x : nat) : myle x (S (S (S x))).
    Proof. auto with core.  Qed.
    

    Please note that the following statement is logically equivalent (according to the definition of addition) but not provable by auto. Even if you add Hint unfold plus : core. as a directive, this won't help because plus is not the head symbol of the goal.

    Lemma myleplus3 (x : nat) : myle x (3 + x).
    Proof.
    auto. (* the goal is unchanged. *)
    simpl. auto.
    Qed.
    

    I often use automatic tactics from Coq, for instance lia, but I always do so because I can predict if the goal is part of the intended scope of the tactic.