CSE773, Tactics and Interactive Help


You will use these tactics often, I have tried to arrange them in order of frequency of use, so in the first few weeks you will use only the those near the top. But a host of fine TACtics have been developed. If you find that you want to do something that makes sense to you, look for a TACtic to do it.
Prof. Morris has helpful notes on tactics including some he created. They are included in the course directory, /home/ecefac/cse773, in compiled form

Other Useful Things:
Example of GEN_TAC
 GEN_TAC 
 Often used as the initial step of a proof 
 Remove the universal quantifier in the goal 
 Suppose the goal is to prove associativity of "/\"

         Initial goal:
         !x y z. x /\ y /\ z = (x /\ y) /\ z
Use GEN_TAC         
- e(GEN_TAC);
to obtain
1 subgoal:
> val it =
    !y z. x /\ y /\ z = (x /\ y) /\ z
    
     : goalstack
with universal quantifier x removed.
Use 
e(REPEAT GEN_TAC) to remove them all.
Use
e(GEN_TAC THEN GEN_TAC); to remove two universal quantifiers

Return to index
Return to tactics list
Example of DISCH_TAC
val it =
    (a x ==> b x) /\ ~b x ==> ~a x
    
     : goalstack
- e(DISCH_TAC);
OK..
1 subgoal:
> val it =
    ~a x
    ------------------------------------
      (a x ==> b x) /\ ~b x
     : goalstack
Return to index
Return to tactics list
Example of CONJ_TAC
Set a goal that is an implication and has a conjuctive conclusion
 g(`!(x:num). (a x==> b x) /\ ~b x ==> (~a x /\ ~~~b x)`); 
> val it =
    Proof manager status: 
         
    1. Incomplete:
         Initial goal:
         !x. (a x ==> b x) /\ ~b x ==> ~a x /\ ~~~b x
         
     : proofs
Now peel off universal quantifier and move antecedent to assumption list
- e(GEN_TAC THEN DISCH_TAC);
OK..
Now you have a conjunctive goal and can prove them separately
1 subgoal:
> val it =
    ~a x /\ ~~~b x
    ------------------------------------
      (a x ==> b x) /\ ~b x
     : goalstack
- e(CONJ_TAC);
OK..
2 subgoals:
> val it =
    ~~~b x
    ------------------------------------
      (a x ==> b x) /\ ~b x
    
    ~a x
    ------------------------------------
      (a x ==> b x) /\ ~b x
     : goalstack
This is an example where the "stack" property of the proof environment
can be seen. The original sequent that was on top of the stack
has been replaced by two sequents on the stack
Return to index
Return to tactics list
Example of STRIP_TAC

STRIP TAC is a combination of GEN_TAC, CONJ_TAC and DISCH_TAC


  1. Incomplete:
         Initial goal:
         !x. (a x ==> b x) /\ ~b x ==> ~a x /\ ~~~b x
         
         
     : proofs
- e(REPEAT STRIP_TAC);
OK..
2 subgoals:
> val it =
    F
    ------------------------------------
      0.  a x ==> b x
      1.  ~b x
      2.  ~~b x
    
    F
    ------------------------------------
      0.  a x ==> b x
      1.  ~b x
      2.  a x
     : goalstack
Return to index
Return to tactics list
Example of UNDISCH_TAC

Use UNDISCH_TAC to move an assumption from the assumption list to the goal, as the antecedent of an implication.

You must specify which assumption to move, so the "Term" function is used. It is frequent that you need to specify the types of the variables mentioned in the argument of Term.


val it =
    F
    ------------------------------------
      0.  a x ==> b x
      1.  ~b x
      2.  ~~b x
     : goalstack
- e(UNDISCH_TAC (Term `~~b (x:num)`));
OK..
1 subgoal:
> val it =
    ~~b x ==> F
    ------------------------------------
      0.  a x ==> b x
      1.  ~b x
     : goalstack
Return to index
Return to tactics list
Example of RES_TAC

Used to do resolution on the assumption list, adding results to the assumption list.

    
    F
    ------------------------------------
      0.  a x ==> b x
      1.  ~b x
      2.  a x
     : goalstack
- e(RES_TAC);
OK..
1 subgoal:
> val it =
    F
    ------------------------------------
      0.  a x ==> b x
      1.  ~b x
      2.  a x
      3.  b x
     : goalstack
Notice the assumption list now has both b x and ~ b x 
as elements. RES_TAC will detect this and since the assumption
list is contradictory, it will declare the sequent true.
False implies everything!!!
- e(RES_TAC);
OK..

Goal proved.
 [..] |- F

Goal proved.
 [...] |- F

Return to index
Return to tactics list
Example of ASM_CASES_TAC

Use in cases where you wish to split the proof in two, with some term true in one and false in the other.


val it =
    ~~b x ==> F
    ------------------------------------
      0.  a x ==> b x
      1.  ~b x
     : goalstack
We will split with b x in one part and ~b x in the other.
- e(ASM_CASES_TAC (Term `(b:num->bool) x`));
OK..
2 subgoals:
> val it =
    ~~b x ==> F
    ------------------------------------
      0.  a x ==> b x
      1.  ~b x
      2.  ~b x
    
    ~~b x ==> F
    ------------------------------------
      0.  a x ==> b x
      1.  ~b x
      2.  b x
     : goalstack
Return to index
Return to tactics list
Example of ASM_REWRITE_TAC

Rewrite the goal using equations in the assumption list.

Writing is left to right. If the left side of an equation from the assumption list appears in the goal, then the goal is rewritten with that occurence replaced by the right side of the equation. If you want right to left replacement, use GSYM conversion

ASM_REWRITE_TAC takes an argument that is a list of theorems. Often you don't have any theorems to include so an empty list is the argument.

ASM_REWRITE_TAC []

The above can be replaced by AR, which is less typing, if you have opened ante_allTacs.


val it =
    ~~b x ==> F
    ------------------------------------
      0.  a x ==> b x
      1.  ~b x
     : goalstack
- e(ASM_REWRITE_TAC []);
OK..

Goal proved.
 [.] |- ~~b x ==> F

Goal proved.
 [..] |- F
> val it =
    Initial goal proved.
    |- !x. (a x ==> b x) /\ ~b x ==> ~a x /\ ~~~b x : goalstack
Return to index
Return to tactics list
Example of LEMMA_TAC, LEMMA_MP_TAC
It is common that you want to prove some smaller fact that will help you in the main proof.
LEMMA_TAC with an argument that is the lemma you want will split the proof, with one goal being the lemma, and the other the original goal. But the second will now have the lemma added to the assumption list.
LEMMA_MP_TAC is the same except that the lemma is added to the goal as an antecedent of an implication with the original goal as conclusion.

e(LEMMA_TAC (Term `t0 < (SUC t) + t0`)
Presumably, the term is needed on the assumption list.
e(LEMMA_MP_TAC (Term `t0 < (SUC t) + t0`)
Presumably the term is needed as the antecedent of an implication with the original goal as conclusion.
Return to index
Return to tactics list


Example of REWRITE_TAC
Used to rewrite the goal with a theorem. The theorem may be from a library, from the current environment, or from the assumption list.
REWRITE_TAC has an argument thet is a list of theorems. Our examples are from the file "parity.txt" which is part of the class notes.
First example uses a theorem from the local environment, where definitions are given.
Second example uses an assumption.
To select the right assumption use "with_asm" , a function that takes an argument that is a string of space-separated variable names to identify the assumption uniquely, then use another function "ulist" to put the selected assumption in a list, suitable for REWRITE_TAC.
1 subgoal:
> val it =
    PARITY_Design f out ==> PARITY_Spec f out
    
     : goalstack
- e(REWRITE_TAC [PARITY_Design_def, PARITY_Spec_def]);
OK..
1 subgoal:
> val it =
    (?next notgate.
       MULTIPLEXER f notgate out next /\ NOT_gate out notgate /\
       REG next out) ==>
    out 0 /\ !t. out (SUC t) = PARITY (SUC t) f
    
     : goalstack
;
So we see that the definitions of PARITY_Design_def and
PARITY_Spec_def have been used.

Later in the same proof we want to use an assumption for rewriting,
but we want the rewriting to be right to left. Use with_asm to
select the assumption. The "fn th" text captures the assumption
as "th". Then include th in the REWRITE_TAC using GSYM to reverse it.

It would have been a simpler tactic if we had not wanted the reversal.
e(with_asm "out t" (REWRITE_TAC o ulist));
would suffice for rewriting left to right.

> val it =
    (if f (SUC t) then ~PARITY (SUC t) f else PARITY (SUC t) f) =
    PARITY (SUC (SUC t)) f
    ------------------------------------
      0.  !t. next t = (if f t then notgate t else out t)
      1.  !t. notgate t = ~out t
      2.  out 0
      3.  !t. out (SUC t) = next t
      4.  out (SUC t) = PARITY (SUC t) f
     : goalstack
- e(with_asm "out t" (fn th => (REWRITE_TAC [(GSYM th)])));
OK..
1 subgoal:
> val it =
    (if f (SUC t) then ~out (SUC t) else out (SUC t)) =
    PARITY (SUC (SUC t)) f
    ------------------------------------
      0.  !t. next t = (if f t then notgate t else out t)
      1.  !t. notgate t = ~out t
      2.  out 0
      3.  !t. out (SUC t) = next t
      4.  out (SUC t) = PARITY (SUC t) f
     : goalstack
Return to index
Return to tactics list
Example of MATCH_MP_TAC
The theorem MOD_EQ_0 is used. MOD is the usual arithmetic MOD. Notice that MATCH_MP_TAC conveniently discovers the needed value for n.
       Initial goal:
         (x * 6) MOD 6 = 0
     : proofs
- MOD_EQ_0;
> val it = |- !n. 0 < n ==> !k. (k * n) MOD n = 0 : thm
- e(MATCH_MP_TAC MOD_EQ_0);
OK..
1 subgoal:
> val it =
    0 < 6
Return to index
Return to tactics list
Example of TAUT_TAC A good tautology checker.
       Initial goal:
         !a b c. (a \/ b) /\ (c \/ ~b) ==> a \/ c
         
         
     : proofs
- e(TAUT_TAC);
OK..
> val it =
    Initial goal proved.
    |- !a b c. (a \/ b) /\ (c \/ ~b) ==> a \/ c : goalstack
Return to index
Return to tactics list
Example of ARITH_TAC A good arithmetic expression checker.
1 subgoal:
> val it =
    (2 ** n - 1 + 1 = 2 ** n) ==> (2 * 2 ** n - 1 + 1 = 2 * 2 ** n)
    
     : goalstack
- e(ARITH_TAC);
OK..

Goal proved.
|- (2 ** n - 1 + 1 = 2 ** n) ==> (2 * 2 ** n - 1 + 1 = 2 * 2 ** n)
Return to index
Return to tactics list
Example of RW_TAC arith_ss []
Good at simplifying the goal, but not always!
In the example arith_ss detects that i<0 must be false, so it simplifies the goal.
  
    (!i. i < 0 ==> ~g i) = (0 = Val 0 g)
    
     : goalstack
- e(RW_TAC arith_ss []);
OK..
1 subgoal:
> val it =
    0 = Val 0 g
    
     : goalstack

Return to index
Return to tactics list
Induction Example The example is from the parity proof included in the class notes. We are seeking to prove that the PARITY_Design satisfies the PARITY_Spec for all n. So we use induction and prove it true for (n=0) and then prove it true for (SUC n) given that it is true for n.
> val it =
    !t. out (SUC t) = PARITY (SUC t) f
    ------------------------------------
      0.  !t. next t = (if f t then notgate t else out t)
      1.  !t. notgate t = ~out t
      2.  out 0
      3.  !t. out (SUC t) = next t
     : goalstack
- e(Induct);
OK..
2 subgoals:
> val it =
    out (SUC (SUC t)) = PARITY (SUC (SUC t)) f
    ------------------------------------
      0.  !t. next t = (if f t then notgate t else out t)
      1.  !t. notgate t = ~out t
      2.  out 0
      3.  !t. out (SUC t) = next t
      4.  out (SUC t) = PARITY (SUC t) f
    
    out (SUC 0) = PARITY (SUC 0) f
    ------------------------------------
      0.  !t. next t = (if f t then notgate t else out t)
      1.  !t. notgate t = ~out t
      2.  out 0
      3.  !t. out (SUC t) = next t
     : goalstack

Return to index
Return to tactics list
IMP_RES_TAC Example This is from our original example, design of a parity network
    !t. out (SUC t) = (if f t then ~out t else out t)
    ------------------------------------
      0.  PARITY_Design f out
      1.  out 0
     : goalstack
- PARITY_Design_Implies;
> val it =
    |- !f out.
         PARITY_Design f out ==>
         !t. out (SUC t) = (if f t then ~out t else out t) : thm
- e(IMP_RES_TAC PARITY_Design_Implies );
OK..

Goal proved.
 [.] |- !t. out (SUC t) = (if f t then ~out t else out t)