ウォンツテック

そでやまのーと

存在の証明 1

Coqをインストールしたので
http://d.hatena.ne.jp/qnighy/20101220/1292829222
この辺を参考に勉強中です。
ついでに自分で命題を考えて証明してみた。


命題は forall (x : nat), x > 1 -> x < x * x. というもの。


こんなもの直感的だろ!
といいたい所ですが、論理学の世界では公理系から演繹(証明)出来ないものは全て不定な存在です。


戦略的にはSearchPatternで (_ < _ * _) を調べ見つけた

mult_lt_compat_r: forall n m p : nat, n < m -> 0 < p -> n * p < m * p

の定理を使う方針で証明していきます。
pをx、nを1、mをxとすると仮定から p n mはnatであり、n < mとなるので定理より命題は成り立ちます。
が、 x < x * x と 1 * x < x * xが同値な命題かどうかを証明しなければなりません。
要は x = 1 * xを証明する必要があります。
証明の途中で仮定化したい補題が発生した場合はassert tacticsでがしがし仮定化し証明していきます。


では証明

Lemma square_is_big:
 forall (x:nat), x > 1 -> x < x*x.
Proof.
 intros.

 (* x = x * 1 の証明 *)
 assert (G: x = x * 1).
 assert (G1: x * O = O).
 apply (mult_0_r x).
 assert (G2: x = x + O).
 apply plus_n_O.
 rewrite G2 at 1.
 assert (G3: x + O = O + x).
 apply plus_comm.
 rewrite G3.
 rewrite <-G1 at 1.
 apply (mult_n_Sm x O).

 (* x < x * x を 1 * x < x * x に変換 *)
 rewrite G at 1.
 assert (G4: x * 1 = 1 * x).
 apply mult_comm.
 rewrite G4.

 (* x > 1 は仮定に存在しているので,後は仮定にx > 0が必要なので証明 *)
 assert (G5: x > 0).
 assert (G6: 1 > 0).
 apply neq_O_lt.
 apply O_S.
 apply (gt_trans x 1 O).
 exact H.
 exact G6.

 (* 条件が整ったので最後の仕上げ *)
 apply mult_lt_compat_r.
 exact H.
 exact G5.
Qed.

x = x * 1とか 1 > 0とかの証明が意外に難しかった。
まぁただ欲しい仮定はassertでどんどん証明していくという事を掴めればなんとかなる。
普通に数学の命題を証明する時と同じ思考回路を使うんだけど SearchPatternで公理、定理を検索出来るからかなり便利。