Course6: Equality Proofs and
Proofs by Induction in Coq

Summary of elementary tactics

In the previous lecture, we considered some elementary tactics, with no or only very little automatisation.
Some basic types (from CPM)
 Writing of propositional formulas (from CPM)
Quantifiers (from CPM)
Here is a reminder:
  • assumption if the current goal is exactly one of the hypothesis (cf. the axiom rule in logic).
  • For all primitive connectors (quantification , implication ):
    • introduction via intro (or one of its variants intros,
    intro x, intros x y ...)
    • elimination via apply H (where H is the name of
    the hypothesis to eliminate).
  • The other connectors (which are actually inductive definitions) may ideally be introduced by constructor and eliminated by destruct H. But the introduction frequently requires more ad-hoc tactics:
    • split for a conjunction (written /\)
    • left and right for a disjunction (written \/)
    • ... (written exists) for a quantification
    (where ... is the place where the existential witness is given)
    • No introduction tactic for False !
    • For True (seldom used in Coq), the introduction can
    be done via constructor, but nothing to eliminate.
  • The simpl tactic performs a conversion on the goal.
  • In Coq, a definition d could be replaced by its body thanks to the tactic unfold d.
  • Some abbreviations:
    • A negation ¬A (written ~A) is just a shortcut for AFalse.
    Hence introduction via intro (or intros a, giving a name forces the introduction) and elimination via apply H or destruct H (whether one wants to focus on the underlying or False).
    • An equivalence AB (written A<->B) is just a shortcut for (AB)/\(BA),
    hence is manipulated as a conjunction of implications.
  • Some automatic tactics : trivial, easy, auto, eauto, intuition, firstorder. See the Coq documentation for more details.
Tactics for introducting and eliminating logical connectives (from CPM)

Today's program

Today, we will mostly focus in equality and induction plus some additional useful features. Here is a little warm-up betfore we enter the details:
The equality is handled by tactics:
  • reflexivity
  • symmetry
  • transitivity ... (where you need to give the intermediate
term) and
  • rewrite ... (give the equality name or lemma to use as a
rewrite rule) or
  • rewrite <- ... (right-to-left rewriting)
Inductive reasoning will be studied at length in coming lectures. Just to state it immediately:
  • induction ... (to do inductive reasoning, to be investigated in the next lectures).

Managing the interactive proof progresses

  • Undo: goes back one tactic
  • Restart: restart the proof from the original goal
  • Abort: Aborts the current proof.
  • Admitted: gives up the current proof and declares the initial goal as an axiom.
  • Focusing using bullets or i: { tac }
  • Applying a tactic to the i-th goal: i:tac, ...
  • Modifying the goal list: all: swap i j
  • Getting information:
    • Show display the current goals;
    • Show Proof displays the current proof term (with holes for open goals).

Composing tactics

Tacticals for composing tactics (from CPM)
Some more:
  • tac ;[tac1 |. . .|tacn]: applies tac to the goal which generates n subgoals and taci is applied to the i-th subgoal.
  • idtac: always succeed, leaving the goal unchanged.
  • fail: always fail (useful to implement a tactic saying: "I solve the goal immediatly or I fail" with tac; fail. Indeed, if tac fails, it fails, if tac succeeds producing at least one subgoal, it fails and if tac suceeds producing no subgoal, it succeeds.
  • try: it behaves like tac || idtac. It is often useful to do tac ; try tac'. Another example is tac; try (tac'; fail). this tries applying tac' to the subgoals generated by tac but only to those which are completely solved by tac', leaving the other ones unchanged.

A tiny bit of automation: auto and trivial

auto recursively composes intros, apply and assumptions until a given depth (by default, it is 5). Either it completely solves the goal, or it leaves the goal unchanged.
trivial is less powerfull that auto but it emphasizes that concluding is easier.

Searching for Lemmas


About nat.

About O.

Search 0.

Search "_comm".

It is possibl to search by describing a pattern of what you are looking for:

Require Import ZArith.

SearchPattern (_ + __)%Z.
SearchPattern (_ × __ × _)%Z.

also non linear patterns:

SearchPattern (?X1 × _ ≤ ?X1 × _)%Z.

SearchPattern (?X1 × _ ≤ ?X1 × _).

Searching only for equalities:

SearchRewrite (1 × _)%Z.

SearchPattern (_ = 1 × _ )%Z.

Equality: eq

Tactics for equality (from CPM)

Print eq.

Syntactic equality : only x is equal to x
Inductive eq (A : Type) (x : A) : A -> Prop :=  eq_refl : eq A x x.
constructor is the reflexivity rule. tactic "reflexivity"

Lemma compute_equal : 2+2 = 4.
Proof.
simpl.
reflexivity.
Qed.

Check eq_ind.

The Leibniz principle, or the rewrite principle :
eq_ind
     : forall (A : Type) (x : A) (P : A -> Prop),
       P x -> forall y : A, x = y -> P y
match on a equality is a form of rewrite the rewrite tactic proceed by a match on the equality

Print eq_ind.

Lemma eq_sym A (x y : A) : x = yy = x.
Proof.
 intro H. Show Proof.
destruct H. Show Proof. reflexivity.
Qed.
Print eq_sym.

If H : a = b is in the context, then rewrite H rewrites occurrences of a into b
On the other hand, rewrite <- H rewrite bs into as.

Open Scope Z_scope.

Theorem Zmult_distr_1: n x: Z, n × x + x = (n+1)* x.
Proof.
intros n x.
Check Zmult_plus_distr_l.
rewrite Zmult_plus_distr_l.
rewrite Zmult_1_l.
reflexivity.
Qed.

It is possible to rewrite in an hypothesis with rewrite H in H'.
When there are multiple occurrences of a terme and one wants to rewrite just one, the pattern tactic comes in handy:
pattern t at i j k.

Theorem regroup : x: Z, x+x+x+x+x = 5 × x.
Proof.
pose Zmult_1_l as H1.
pose Zmult_distr_1 as H2.
intro x.
(* rewrite <- H1. *)
pattern x at 1.
rewrite <- H1.
repeat rewrite H2.
reflexivity.
(* trivial. *)
(* auto.*)
Qed.

When using a rewrite on a conditional goal, that may generate subgoals.

Require Import Arith.
Open Scope nat_scope.

Section Condrewrite.
Hypothesis le_lt_S_eq : n p: nat,
npp < S nn=p.

Lemma cond_rewrite_example: n: nat,
8 < n+6 → 3+n < 6 → n×n = n+n.
Proof.
intros n H H0.
pose (le_lt_S_eq 2 n) as H2.
rewrite <- H2.
reflexivity.
(* simpl; auto. *)
apply Nat.add_le_mono_l with (p := 6).
rewrite Nat.add_comm in H; simpl; auto with arith.
apply Nat.add_le_mono_l with (p :=3); auto with arith.
Qed.

End Condrewrite.

nat and induction


Print nat.
Check nat_ind.
Print nat_ind. (* fixpoint + match *)

Lemma test_induction1 : n:nat, n=n.
intro n.
elim n.
- reflexivity.
- intros n0 Hrec.
reflexivity.
Qed.

Lemma test_induction2 : n:nat, n=n.
intro n.
destruct n.
- reflexivity.
- reflexivity.
Qed.

Lemma test_induction3 : n:nat, n=n.
induction n.
- reflexivity.
- reflexivity.
Show Proof.
Abort.

Lemma test_induction4 : H: Prop, H n:nat, n=n.
induction n.
- reflexivity.
- reflexivity.
Show Proof.
Abort.

Print "+".

2+2 = Nat.add (S (S 0)) 2.
    = match S (S 0) with
      | 0 => m
      | S p => S (add p 2)
     (* unfold rule for fixpoint : a fixpoint applied to a constructor can
        unfold once *)
    = S (add (S 0) 2)
    = ...
    = 4
Compute 2+2.

Require Import Arith.
Check Nat.add_succ_l.

Lemma non_compute_proof : 2+2 = 4.
Proof.
 rewrite Nat.add_succ_l.
 rewrite Nat.add_succ_l.
 rewrite Nat.add_0_l.
 reflexivity.
Qed.
Print non_compute_proof.
Print Nat.add_succ_l.

Lemma compute_proof : 2+2 = 4.
(* in coq, most of the time we're modulo computation :
   2+2 just the same as 4 *)

 simpl. (* force a computation *)
 reflexivity.
Set Printing Implicit.
Show Proof.
Check (@eq_refl nat 4).
(* 2+2=4 and 4=4 are the *same* statement (modulo computation) :
    (what we call *convertible* )
   they can be proved by the *same* proof term *)

Qed.

Lemma compute_proof' : 2+2 = 4.
reflexivity.
Qed.

Definition compute_proof'' : 2+2 = 4 := eq_refl.
                                 (* or more precisely @eq_refl nat 4 *)


This page has been generated by coqdoc