HOL4 の証明例(1)

等比数列の和です.

g `!n. sum(0,SUC n) (\n. &2 pow n) = &2 pow (SUC n) - &1`;
e( Induct_on `n` );
e( RW_TAC(real_ss++REAL_ARITH_ss)[pow, SUM_1] );
e( RW_TAC(real_ss++REAL_ARITH_ss)[pow, sum] );

- g `!n. sum(0,SUC n) (\n. 2 pow n) = 2 pow (SUC n) - 1`;
> val it =
    Proof manager status: 1 proof.
    1. Incomplete goalstack:
         Initial goal:

         !n. sum (0,SUC n) (\n. 2 pow n) = 2 pow SUC n - 1


     : proofs
- e( Induct_on `n` );
OK..
2 subgoals:
> val it =

    sum (0,SUC (SUC n)) (\n. 2 pow n) = 2 pow SUC (SUC n) - 1
    ------------------------------------
      sum (0,SUC n) (\n. 2 pow n) = 2 pow SUC n - 1


    sum (0,SUC 0) (\n. 2 pow n) = 2 pow SUC 0 - 1

     : proof
- e( RW_TAC(real_ss++REAL_ARITH_ss)[pow, SUM_1] );
OK..

Goal proved.
 [] |- sum (0,SUC 0) (\n. 2 pow n) = 2 pow SUC 0 - 1

Remaining subgoals:
> val it =

    sum (0,SUC (SUC n)) (\n. 2 pow n) = 2 pow SUC (SUC n) - 1
    ------------------------------------
      sum (0,SUC n) (\n. 2 pow n) = 2 pow SUC n - 1
     : proof
- e( RW_TAC(real_ss++REAL_ARITH_ss)[pow, sum] );
OK..

Goal proved.
 [sum (0,SUC n) (\n. 2 pow n) = 2 pow SUC n - 1]
|- sum (0,SUC (SUC n)) (\n. 2 pow n) = 2 pow SUC (SUC n) - 1
> val it =
    Initial goal proved.
     [] |- !n. sum (0,SUC n) (\n. 2 pow n) = 2 pow SUC n - 1 : proof

HOL Light では

g `!n. sum(0,SUC n) (\n. &2 pow n) = &2 pow (SUC n) - &1`;;
e( INDUCT_TAC );;
e( REWRITE_TAC[pow; sum; REAL_ADD_LID; ADD] THEN REAL_ARITH_TAC );;
e( ASM_REWRITE_TAC[pow; sum; ADD] THEN REAL_ARITH_TAC );;

# g `!n. sum(0,SUC n) (\n. &2 pow n) = &2 pow (SUC n) - &1`;;
val it : goalstack = 1 subgoal (1 total)

`!n. sum (0,SUC n) (\n. &2 pow n) = &2 pow SUC n - &1`

# e( INDUCT_TAC );;
val it : goalstack = 2 subgoals (2 total)

  0 [`sum (0,SUC n) (\n. &2 pow n) = &2 pow SUC n - &1`]

`sum (0,SUC (SUC n)) (\n. &2 pow n) = &2 pow SUC (SUC n) - &1`

`sum (0,SUC 0) (\n. &2 pow n) = &2 pow SUC 0 - &1`

# e( REWRITE_TAC[pow; sum; REAL_ADD_LID; ADD] THEN REAL_ARITH_TAC );;
val it : goalstack = 1 subgoal (1 total)

  0 [`sum (0,SUC n) (\n. &2 pow n) = &2 pow SUC n - &1`]

`sum (0,SUC (SUC n)) (\n. &2 pow n) = &2 pow SUC (SUC n) - &1`

# e( ASM_REWRITE_TAC[pow; sum; ADD] THEN REAL_ARITH_TAC );;
val it : goalstack = No subgoals

なので,この程度なら HOL4 の方が簡潔です.

 しかし,分数になると...

g `!n. sum(0,SUC n) (\n. (&1/ &2) pow n) = &2 - (&1 / &2) pow n`;;
e( INDUCT_TAC );;
e( REWRITE_TAC[pow; sum; REAL_ADD_LID; ADD] THEN REAL_ARITH_TAC );;
e( ASM_REWRITE_TAC[pow; sum; ADD] THEN REAL_ARITH_TAC );;

# g `!n. sum(0,SUC n) (\n. (&1/ &2) pow n) = &2 - (&1 / &2) pow n`;;
val it : goalstack = 1 subgoal (1 total)

`!n. sum (0,SUC n) (\n. (&1 / &2) pow n) = &2 - (&1 / &2) pow n`

# e( INDUCT_TAC );;
val it : goalstack = 2 subgoals (2 total)

  0 [`sum (0,SUC n) (\n. (&1 / &2) pow n) = &2 - (&1 / &2) pow n`]

`sum (0,SUC (SUC n)) (\n. (&1 / &2) pow n) = &2 - (&1 / &2) pow SUC n`

`sum (0,SUC 0) (\n. (&1 / &2) pow n) = &2 - (&1 / &2) pow 0`

# e( REWRITE_TAC[pow; sum; REAL_ADD_LID; ADD] THEN REAL_ARITH_TAC );;
val it : goalstack = 1 subgoal (1 total)

  0 [`sum (0,SUC n) (\n. (&1 / &2) pow n) = &2 - (&1 / &2) pow n`]

`sum (0,SUC (SUC n)) (\n. (&1 / &2) pow n) = &2 - (&1 / &2) pow SUC n`

# e( ASM_REWRITE_TAC[pow; sum; ADD] THEN REAL_ARITH_TAC );;
val it : goalstack = No subgoals

のように HOL Light が全く動じないのに対して,HOL4 は大変です.

g `!n. sum(0,SUC n) (\n. (1/ 2) pow n) = 2 - (1 / 2) pow n`;
e( Induct_on `n` );
e(RW_TAC(real_ss++REAL_ARITH_ss)[pow, SUM_1]);
val lem0 = METIS_PROVE[POW_NZ, REAL_ARITH``2<>0:real``, REAL_ENTIRE, mult_ratr, REAL_DIV_LMUL_CANCEL]``(2 * (1 / (2 * 2 pow n)))=(1 / 2 pow n)``;
val lem1 = REAL_ARITH``(2 - 1 / 2 pow n + 1 / (2 * 2 pow n) = 2 - 1 / (2 * 2 pow n))<=>(2 * (1 / (2 * 2 pow n)) = 1 / 2 pow n)``;
e(RW_TAC(real_ss++REAL_ARITH_ss)[pow, sum, POW_ONE, lem0, lem1]);

- g `!n. sum(0,SUC n) (\n. (1/ 2) pow n) = 2 - (1 / 2) pow n`;
> val it =
    Proof manager status: 1 proof.
    1. Incomplete goalstack:
         Initial goal:

         !n. sum (0,SUC n) (\n. (1 / 2) pow n) = 2 - (1 / 2) pow n


     : proofs
- e( Induct_on `n` );
OK..
2 subgoals:
> val it =

    sum (0,SUC (SUC n)) (\n. (1 / 2) pow n) = 2 - (1 / 2) pow SUC n
    ------------------------------------
      sum (0,SUC n) (\n. (1 / 2) pow n) = 2 - (1 / 2) pow n


    sum (0,SUC 0) (\n. (1 / 2) pow n) = 2 - (1 / 2) pow 0

     : proof
- e(RW_TAC(real_ss++REAL_ARITH_ss)[pow, SUM_1]);
OK..

Goal proved.
 [] |- sum (0,SUC 0) (\n. (1 / 2) pow n) = 2 - (1 / 2) pow 0

Remaining subgoals:
> val it =

    sum (0,SUC (SUC n)) (\n. (1 / 2) pow n) = 2 - (1 / 2) pow SUC n
    ------------------------------------
      sum (0,SUC n) (\n. (1 / 2) pow n) = 2 - (1 / 2) pow n
     : proof
- val lem0 = METIS_PROVE[POW_NZ, REAL_ARITH``2<>0:real``, REAL_ENTIRE, mult_ratr, REAL_DIV_LMUL_CANCEL]``(2 * (1 / (2 * 2 pow n)))=(1 / 2 pow n)``;
metis: r[+0+10]+0+0+0+0+0+0+0+2+7+2+0+4+3+6+7+1+11+13+11+10+13r+5+11+16+9+1
2+2+3+13+1#
> val lem0 =  [] |- 2 * (1 / (2 * 2 pow n)) = 1 / 2 pow n : thm
- val lem1 = REAL_ARITH``(2 - 1 / 2 pow n + 1 / (2 * 2 pow n) = 2 - 1 / (2 * 2 pow n))<=>(2 * (1 / (2 * 2 pow n)) = 1 / 2 pow n)``;
> val lem1 =
     []
    |- (2 - 1 / 2 pow n + 1 / (2 * 2 pow n) = 2 - 1 / (2 * 2 pow n)) <=>
       (2 * (1 / (2 * 2 pow n)) = 1 / 2 pow n) : thm
- e(RW_TAC(real_ss++REAL_ARITH_ss)[pow, sum, POW_ONE, lem0, lem1]);
OK..

Goal proved.
 [sum (0,SUC n) (\n. (1 / 2) pow n) = 2 - (1 / 2) pow n]
|- sum (0,SUC (SUC n)) (\n. (1 / 2) pow n) = 2 - (1 / 2) pow SUC n
> val it =
    Initial goal proved.
     [] |- !n. sum (0,SUC n) (\n. (1 / 2) pow n) = 2 - (1 / 2) pow n : proof

これを HOL4 の力不足と見るか,計算をブラックボックスにしない高潔な理念の現われと見るかは...

おまけ

- TOP_DEPTH_CONV num_CONV ``5:num``;
> val it =  [] |- 5 = SUC (SUC (SUC (SUC (SUC 0)))) : thm

- (TOP_DEPTH_CONV num_CONV THENC REWRITE_CONV[pow, REAL_MUL_RID]) ``x pow 5``;
> val it =  [] |- x pow 5 = x * (x * (x * (x * x))) : thm