8.1 The goalstack (2)
今回は,量化,論理結合,対称式を含んだ
# g `!x y:real. &0 < x * y ==> (&0 < x <=> &0 < y)`;;
val it : goalstack = 1 subgoal (1 total)`!x y. &0 < x * y ==> (&0 < x <=> &0 < y)`
を場合分けを用いて証明します.なお,証明自体は,REAL_FIELDでは
# REAL_FIELD `!x y. &0 < x*y ==> (&0
&0
と失敗しますが,MESONに
# REAL_LT_MUL_EQ;;
val it : thm =
|- (!x y. &0 < x ==> (&0 < x * y <=> &0 < y)) /\
(!x y. &0 < y ==> (&0 < x * y <=> &0 < x))
(探し方は後述)を参照させると
# MESON [REAL_LT_MUL_EQ] `!x y. &0 < x*y ==> (&0
&0 (&0 < y <=> &0 < x)
のように処理してくれます.
ではまず,可能な限り繰り返しの tactic を生成する REPEAT(: tactic -> tactic =
# e ( REPEAT GEN_TAC );;
val it : goalstack = 1 subgoal (1 total)`&0 < x * y ==> (&0 < x <=> &0 < y)`
なので,前件を仮定にまわすと
# e ( DISCH_TAC );;
val it : goalstack = 1 subgoal (1 total)0 [`&0 < x * y`]
`&0 < x <=> &0 < y`
となります.なお,STRIP_TAC は subgoalの形に応じて,GEN_TAC,CONJ_TAC(連言の分解),DISCH_TAC を実行しますので,次のようにもできます.
...
`!x y. &0 < x * y ==> (&0 < x <=> &0 < y)`
# e ( REPEAT STRIP_TAC );;
val it : goalstack = 1 subgoal (1 total)0 [`&0 < x * y`]
`&0 < x <=> &0 < y`
次に,EQ_TAC で equivalent を2つの implies に分解します.
# e ( EQ_TAC ) ;;
val it : goalstack = 2 subgoals (2 total)0 [`&0 < x * y`]
`&0 < y ==> &0 < x`
0 [`&0 < x * y`]
`&0 < x ==> &0 < y`
subgoalsが2個になりましたが,e 関数は,表示されている最も下のsubgoalに対して作用しますので,その証明を考えましょう.
普通ならy=(x*y)/xですが,今回は場合分けの紹介なので,yの符号についての場合分けで行きます.つまり
# REAL_ARITH `&0 < y \/ &0 <= --y`;;
val it : thm = |- &0 < y \/ &0 <= --y
というtheoremを,theoremを引数に取るtheorem tacticである,場合分けの DISJ_CASES_TAC(: thm_tactic =
# e ( DISJ_CASES_TAC ( REAL_ARITH `&0 < y \/ &0 <= --y` ) );;
val it : goalstack = 2 subgoals (3 total)0 [`&0 < x * y`]
1 [`&0 <= --y`]`&0 < x ==> &0 < y`
0 [`&0 < x * y`]
1 [`&0 < y`]`&0 < x ==> &0 < y`
となりますが,下側の結論はその仮定より直ちに得られるので
# e ( ASM_REWRITE_TAC[] ) ;;
val it : goalstack = 1 subgoal (2 total)0 [`&0 < x * y`]
1 [`&0 <= --y`]`&0 < x ==> &0 < y`
に絞れます.
ところが,仮定の`&0 <= --y`から結論の後件`&0 < y`を得るのはどう見ても無理です.困りましたね(笑).
お判りのように,この2つの仮定と結論の前件の連言は F なので,任意の p に対して |- F ==> p という話で,普通に言えば「この場合は起こり得ないので」ということです.
実際に連言が F であることを示すには
# TAUT `( p ==> ( q ==> r ) ) <=> ( ( p /\ q ) ==> r )` ;;
val it : thm = |- p ==> q ==> r <=> p /\ q ==> r
および,==> が右結合であることから
p1 ==> p2 ==> ... ==> pn ==> q(n+1)
が
( p1 /\ p2 /\ ... /\ pn ) ==> q(n+1)
と等価であることに注意しながら,`&0
# e ( MP_TAC (ASSUME`&0<= --y`) );;
val it : goalstack = 1 subgoal (2 total)0 [`&0 < x * y`]
1 [`&0 <= --y`]`&0 <= --y ==> &0 < x ==> &0 < y`
# e ( MP_TAC (ASSUME`&0
&0 <= --y ==> &0 < x ==> &0 < y` # e( MP_TAC ( SPECL [ `x:real` ; `--y` ] REAL_LE_MUL ) ) ;;
val it : goalstack = 1 subgoal (2 total)0 [`&0 < x * y`]
1 [`&0 <= --y`]`(&0 <= x /\ &0 <= --y ==> &0 <= x * --y)
==> &0 < x * y
==> &0 <= --y
==> &0 < x
==> &0 < y`# e( MP_TAC ( REAL_ARITH `&0
&0<=x` ) ) ;;
val it : goalstack = 1 subgoal (2 total)0 [`&0 < x * y`]
1 [`&0 <= --y`]`(&0 < x ==> &0 <= x)
==> (&0 <= x /\ &0 <= --y ==> &0 <= x * --y)
==> &0 < x * y
==> &0 <= --y
==> &0 < x
==> &0 < y`# e( MP_TAC ( REAL_ARITH `&0
~(&0<=x*(--y))` ) ) ;;
val it : goalstack = 1 subgoal (2 total)0 [`&0 < x * y`]
1 [`&0 <= --y`]`(&0 < x * y ==> ~(&0 <= x * --y))
==> (&0 < x ==> &0 <= x)
==> (&0 <= x /\ &0 <= --y ==> &0 <= x * --y)
==> &0 < x * y
==> &0 <= --y
==> &0 < x
==> &0 < y`
これで結論の &0
# e ( MESON_TAC [] );;
0..0..solved at 2
0..0..solved at 3
0..0..solved at 2
0..0..solved at 3
0..0..solved at 2
0..0..solved at 3
0..0..solved at 2
0..0..solved at 3
0..0..solved at 2
0..0..solved at 2
0..0..solved at 2
0..0..solved at 2
val it : goalstack = 1 subgoal (1 total)0 [`&0 < x * y`]
`&0 < y ==> &0 < x`
上のtheorem REAL_LE_MULを見つけるには,search(: term list -> (string * thm) list =
# search[ `&0<=x` ; `&0<=x*y` ];;
val it : (string * thm) list =
[("REAL_LE_MUL", |- !x y. &0 <= x /\ &0 <= y ==> &0 <= x * y);
("REAL_LE_MUL_EQ",
|- (!x y. &0 < x ==> (&0 <= x * y <=> &0 <= y)) /\
(!x y. &0 < y ==> (&0 <= x * y <=> &0 <= x)));
("REAL_LE_SQUARE", |- !x. &0 <= x * x);
("REAL_MUL_POS_LE",
|- !x y.
&0 <= x * y <=>
x = &0 \/ y = &0 \/ &0 < x /\ &0 < y \/ x < &0 /\ y < &0)]
引数のリストの要素は,name"theoremの名前の一部"や omit`除外するterm` も使えます.