8.1 The goalstack (3)
前回残した
...
val it : goalstack = 1 subgoal (1 total)0 [`&0 < x * y`]
`&0 < y ==> &0 < x`
は,先のsubgoalのx,yを交換したものなので,同様に
# e ( DISJ_CASES_TAC ( REAL_ARITH `&0
&0 < x` 0 [`&0 < x * y`]
1 [`&0 < x`]`&0 < y ==> &0 < x`
# e ( ASM_REWRITE_TAC[] );;
val it : goalstack = 1 subgoal (1 total)0 [`&0 < x * y`]
1 [`&0 <= --x`]`&0 < y ==> &0 < x`
と展開すればよいのですが,ここからは少し手を代えてみましょう.
その1)前回は,仮定を前件にまわすために
e ( MP_TAC ( ASSUME `&0 < x * y` ) ) ;;
...
としましたが,前件に追加するtheoremsも仮定に加え,それらをまとめて前件にまわしてみます.
# e ( ASSUME_TAC ( REAL_ARITH `&0
&0<=y` ) );;
val it : goalstack = 1 subgoal (1 total)0 [`&0 < x * y`]
1 [`&0 <= --x`]
2 [`&0 < y ==> &0 <= y`]`&0 < y ==> &0 < x`
# e ( ASSUME_TAC ( SPECL [ `--x` ; `y:real` ] REAL_LE_MUL ) ) ;;
val it : goalstack = 1 subgoal (1 total)0 [`&0 < x * y`]
1 [`&0 <= --x`]
2 [`&0 < y ==> &0 <= y`]
3 [`&0 <= --x /\ &0 <= y ==> &0 <= --x * y`]`&0 < y ==> &0 < x`
# e ( ASSUME_TAC ( REAL_ARITH `&0
~(&0<=(--x)*y)` ) );;
val it : goalstack = 1 subgoal (1 total)0 [`&0 < x * y`]
1 [`&0 <= --x`]
2 [`&0 < y ==> &0 <= y`]
3 [`&0 <= --x /\ &0 <= y ==> &0 <= --x * y`]
4 [`&0 < x * y ==> ~(&0 <= --x * y)`]`&0 < y ==> &0 < x`
そして,仮定の中で適用可能なものに theorem-tactic ttmを施し,その仮定を除去する(除去しない版は FIRST_ASSUM) tactic を生成する FIRST_X_ASSUM(: thm_tactic -> tactic =
# e ( REPEAT ( FIRST_X_ASSUM ( MP_TAC ) ) );;
val it : goalstack = 1 subgoal (1 total)`&0 < x * y
==> &0 <= --x
==> (&0 < y ==> &0 <= y)
==> (&0 <= --x /\ &0 <= y ==> &0 <= --x * y)
==> (&0 < x * y ==> ~(&0 <= --x * y))
==> &0 < y
==> &0 < x`# e ( MESON_TAC [] );;
0..0..solved at 2
0..0..solved at 2
0..0..solved at 2
0..0..solved at 2
0..0..solved at 2
0..0..solved at 2
0..0..solved at 2
0..0..solved at 2
0..0..solved at 2
0..0..solved at 2
0..0..solved at 2
0..0..solved at 2
val it : goalstack = No subgoals
となります.
その2)最後のsubgoalもREAL_ARITH_TACで評価するなら
# REAL_ARITH `&0 < x * y
==> &0 <= --x
==> (&0 <= --x /\ &0 <= y ==> &0 <= --x * y)
==> &0 < y
==> &0 < x`;;
val it : thm =
|- &0 < x * y
==> &0 <= --x
==> (&0 <= --x /\ &0 <= y ==> &0 <= --x * y)
==> &0 < y
==> &0 < x
で十分なので,REAL_LE_MULのみをMP_TACで導入して
...
val it : goalstack = 1 subgoal (1 total)0 [`&0 < x * y`]
1 [`&0 <= --x`]`&0 < y ==> &0 < x`
# e ( REPEAT ( FIRST_X_ASSUM MP_TAC ) );;
val it : goalstack = 1 subgoal (1 total)`&0 < x * y ==> &0 <= --x ==> &0 < y ==> &0 < x`
# e ( MP_TAC ( SPECL [ `--x` ; `y:real` ] REAL_LE_MUL ) ) ;;
val it : goalstack = 1 subgoal (1 total)`(&0 <= --x /\ &0 <= y ==> &0 <= --x * y)
==> &0 < x * y
==> &0 <= --x
==> &0 < y
==> &0 < x`# e ( REAL_ARITH_TAC ) ;;
val it : goalstack = No subgoals
つまり
...
val it : goalstack = 1 subgoal (1 total)0 [`&0 < x * y`]
1 [`&0 <= --x`]`&0 < y ==> &0 < x`
# e ( REPEAT ( FIRST_X_ASSUM MP_TAC ) THEN
MP_TAC ( SPECL [ `--x` ; `y:real` ] REAL_LE_MUL ) THEN REAL_ARITH_TAC
) ;;
val it : goalstack = No subgoals
ともできます.
その3)一般に
# TAUT `(p==>q) <=> ( (p/\(~q))==>F)`;;
val it : thm = |- p ==> q <=> p /\ ~q ==> F
であり,&0<= --x は ~(&0
# REAL_ARITH`(&0 <= --x /\ &0 <= y ==> &0 <= --x * y)
==> &0 < x * y
==> &0 < y
==> &0 < x`;;
val it : thm =
|- (&0 <= --x /\ &0 <= y ==> &0 <= --x * y)
==> &0 < x * y
==> &0 < y
==> &0 < x
で良いわけです.さらに,==> の結合を明記すると,この式は
`(&0 <= --x /\ &0 <= y ==> &0 <= --x * y)
==>( &0 < x * y ==> (&0 < y ==> &0 < x) )`;;
なので,initial goal の本体
`&0 < x * y ==> (&0 < y <=> &0 < x)`
の半分が
`(&0 <= --x /\ &0 <= y ==> &0 <= --x * y)`
のみから得られることが判ります.これにより,場合分けを用いない全体の証明として
# g ( `!x y. &0 < x * y ==> (&0 < x <=> &0 < y)` ) ;;
val it : goalstack = 1 subgoal (1 total)`!x y. &0 < x * y ==> (&0 < x <=> &0 < y)`
# e ( REPEAT GEN_TAC );;
val it : goalstack = 1 subgoal (1 total)`&0 < x * y ==> (&0 < x <=> &0 < y)`
# e( MP_TAC ( SPECL [ `x:real` ; `--y` ] REAL_LE_MUL ) ) ;;
val it : goalstack = 1 subgoal (1 total)`(&0 <= x /\ &0 <= --y ==> &0 <= x * --y)
==> &0 < x * y
==> (&0 < x <=> &0 < y)`# e( MP_TAC ( SPECL [ `--x` ; `y:real` ] REAL_LE_MUL ) ) ;;
val it : goalstack = 1 subgoal (1 total)`(&0 <= --x /\ &0 <= y ==> &0 <= --x * y)
==> (&0 <= x /\ &0 <= --y ==> &0 <= x * --y)
==> &0 < x * y
==> (&0 < x <=> &0 < y)`# e ( REAL_ARITH_TAC );;
val it : goalstack = No subgoals
まとめて
# prove ( `!x y. &0 < x * y ==> (&0 < x <=> &0 < y)` ,
( REPEAT GEN_TAC ) THEN
( MP_TAC ( SPECL [ `x:real` ; `--y` ] REAL_LE_MUL ) ) THEN
( MP_TAC ( SPECL [ `--x` ; `y:real` ] REAL_LE_MUL ) ) THEN
( REAL_ARITH_TAC ) );;
val it : thm = |- !x y. &0 < x * y ==> (&0 < x <=> &0 < y)
を得ます.