(** * Auto: More Automation *)
Set Warnings "-notation-overridden,-parsing".
(** Up to now, we've used the more manual part of Coq's tactic facilities.  In this chapter, we'll learn more about some of Coq's powerful automation features: proof search via the [auto] tactic, automated forward reasoning via the [Ltac] hypothesis matching machinery, and deferred instantiation of existential variables using [eapply] and [eauto].  Using these features together with Ltac's scripting facilities will enable us to make our proofs startlingly short!  Used properly, they can also make proofs more maintainable and robust to changes in underlying definitions.  A deeper treatment of [auto] and [eauto] can be found in the [UseAuto] chapter.  There's another major category of automation we haven't discussed much yet, namely built-in decision procedures for specific kinds of problems: [omega] is one example, but there are others.  This topic will be deferred for a while longer.  Our motivating example will be this proof, repeated with just a few small changes from the [Imp] chapter.  We will simplify this proof in several stages. *)
Ltac inv H := inversion H; subst; clear H.
(** The [auto] tactic frees us from this drudgery by _searching_ for a sequence of applications that will prove the goal *)
Example auto_example_1' : forall (P Q R: Prop),
(P -> Q) -> (Q -> R) -> P -> R.
(** The [auto] tactic solves goals that are solvable by any combination of - [intros] and - [apply] (of hypotheses from the local context, by default). *)
(** Using [auto] is always "safe" in the sense that it will never fail and will never change the proof state: either it completely solves the current goal, or it does nothing. *)
(** Here is a more interesting example showing [auto]'s power: *)
Example auto_example_2 : forall P Q R S T U : Prop,
(P -> Q) ->
(P -> R) ->
(T -> R) ->
(S -> T -> U) ->
((P->Q) -> (P->S)) ->
T ->
P ->
U.
(** When searching for potential proofs of the current goal, [auto] considers the hypotheses in the current context together with a _hint database_ of other lemmas and constructors.  Some common lemmas about equality and logical operators are installed in this hint database by default. *)
Example auto_example_4 : forall P Q R : Prop,
Q ->
(Q -> R) ->
P \/ (Q /\ R).
(** Of course, in any given development there will probably be some specific constructors and lemmas that are used very often in proofs.  We can add these to the global hint database by writing  Hint Resolve T.  at the top level, where [T] is a top-level theorem or a constructor of an inductively defined proposition (i.e., anything whose type is an implication).  As a shorthand, we can write  Hint Constructors c.  to tell Coq to do a [Hint Resolve] for _all_ of the constructors from the inductive definition of [c].  It is also sometimes necessary to add  Hint Unfold d.  where [d] is a defined symbol, so that [auto] knows to expand uses of [d], thus enabling further possibilities for applying lemmas that it knows about. *)
Hint Resolve le_antisym.
Example auto_example_6' : forall n m p : nat,
(n<= p -> (n <= m /\ m <= n)) ->
n <= p ->
n = m.
Definition is_fortytwo x := x = 42.
Example auto_example_7: forall x, (x <= 42 /\ 42 <= x) -> is_fortytwo x.
(** When we are using a particular tactic many times in a proof, we can use a variant of the [Proof] command to make that tactic into a default within the proof.  Saying [Proof with t] (where [t] is an arbitrary tactic) allows us to use [t1...] as a shorthand for [t1;t] within the proof.  As an illustration, here is an alternate version of the previous proof, using [Proof with auto]. *)
Proof with auto.
intros c st st1 st2 E1 E2;
generalize dependent st2;
induction E1;
intros st2 E2; inv E2...
- (* E_Seq *)
assert (st' = st'0) as EQ1...
subst st'0...
- (* E_IfTrue *)
+ (* b evaluates to false (contradiction) *)
rewrite H in H5. inversion H5.
- (* E_IfFalse *)
+ (* b evaluates to true (contradiction) *)
rewrite H in H5. inversion H5.
- (* E_WhileFalse *)
+ (* b evaluates to true (contradiction) *)
rewrite H in H2. inversion H2.
(* E_WhileTrue *)
- (* b evaluates to false (contradiction) *)
rewrite H in H4. inversion H4.
- (* b evaluates to true *)
assert (st' = st'0) as EQ1...
subst st'0...
Qed.
(* ################################################################# *)
(** * Searching For Hypotheses *)
(** The proof has become simpler, but there is still an annoying amount of repetition. Let's start by tackling the contradiction cases. Each of them occurs in a situation where we have both  H1: beval st b = false  and  H2: beval st b = true  as hypotheses.  The contradiction is evident, but demonstrating it is a little complicated: we have to locate the two hypotheses [H1] and [H2] and do a [rewrite] following by an [inversion].  We'd like to automate this process.  (In fact, Coq has a built-in tactic [congruence] that will do the job in this case.  But we'll ignore the existence of this tactic for now, in order to demonstrate how to build forward search tactics by hand.)  As a first step, we can abstract out the piece of script in question by writing a little function in Coq's tactic programming language, Ltac. *)
Ltac rwinv H1 H2 := rewrite H1 in H2; inv H2.

Theorem ceval_deterministic'': forall c st st1 st2,
c / st \\ st1  ->
c / st \\ st2 ->
st1 = st2.