情報科学概論 第3回 1 帰納法 〜帰納法による証明〜 2 場合分けに名前をつける 3 Caseタクティック: 場合分けに名前をつける 1 ... 2 ... 3 ... 4 ... 5 ... • 場合分けが多いと分かりにくい • 字下げ,コメントも理解の助けだが.. Theorem andb_true_elim1 : ∀b c : bool, andb b c = true → b = true. 1 ... 2 ... 3 ... 4 ... 5 ... 6 ... 7 ... Proof. intros b c H. destruct b. Case "b = true". (* <----- here *) reflexivity. Case "b = false". (* <---- and here *) rewrite ← H. reflexivity. Qed. 4 推奨するコーディングスタイル • 必ず字下げをする • 必要に応じてコメントをつける • Caseタクティックを使う – サブケースは SCase – サブサブケースは SSCase – ... • 一行の長さは,長すぎず短すぎず – 1行80文字以内を目安 5 単純化による証明の限界 Theorem plus_0_r_firsttry : n + 0 = n. ∀n:nat, 第一引数で 再帰 Fixpoint plus (n m : nat) : nat := match n with | O => m | S n' => S (plus n' m) end. 6 場合分けによる証明の限界 Theorem plus_0_r_secondtry : ∀n:nat, n + 0 = n. Proof. intros n. destruct n as [| n']. Case "n = 0". reflexivity. (* ここまではよいが... *) Case "n = S n'". simpl. (* ...ここで止まってしまう *) Admitted. 7 帰納法(高校の復習) ∀n. P(n) ⇔ • P(0) • ∀n'. P(n') ⇒ P(S(n')) こちらを証明すれば, 上が言えたことに 帰納法の仮定 (IH: Induction Hypothesis) 8 帰納法の例 ∀n. n + 0 = n ⇔ • 0+0=0 • ∀n'. n' + 0 = n' ⇒ S n' + 0 = S n' 0+0=0 (+の定義) S n' + 0 = S (n' + 0) (+の定義) = S n' (∵IH) 9 帰納法による証明 Theorem plus_0_r : ∀n:nat, n + 0 = n. Proof. intros n. induction n as [| n']. intro Case "n = 0". reflexivity. パターン Case "n = S n'". simpl. rewrite Qed. → IHn'. reflexivity. 帰納法の 仮定 10 証明中の証明 • 先に証明した定理を使用できる • 証明中で"小定理"が必要なことがある – ほぼ自明 – 命名しても他で使用されない ⇒ assert タクティックが便利 11 assert タクティック Theorem mult_0_plus' : ∀n m : nat, (0 + n) * m = n * m. Proof. intros n m. assert (H: 0 + n = n). Case "Proof of assertion". reflexivity. rewrite → H. reflexivity. Qed. 読みやすくなるし, assert の証明の 完了も明確に 12 rewrite タクティックの難点 Theorem plus_rearrange_firsttry : ∀n m p q : nat, (n + m) + (p + q) = (m + n) + (p + q). Proof. intros n m p q. (* (n + m) を (m + n) に書き換えたいだけ... plus_comm でうまくいきそう! *) rewrite → plus_comm. (* いかない...Coq は中央の + を書き換える! *) Admitted. 13 assert タクティックによる解決 Theorem plus_rearrange : ∀n m p q : nat, (n + m) + (p + q) = (m + n) + (p + q). Proof. intros n m p q. assert (H: n + m = m + n). Case "Proof of assertion". → plus_comm. reflexivity. → H. reflexivity. Qed. rewrite rewrite 14 証明 非形式的 vs 形式的 • 「アルゴリズム」 • 「コード」 • アイデアを 効率的に伝達可 • 機械的に正しさの チェック可能 • 人間のみ • Coqでも! 15 形式的証明の例:+ は結合的 Theorem plus_assoc' : ∀n m p : nat, n + (m + p) = (n + m) + p. Proof. intros n m p. induction n as [| n']. reflexivity. simpl. rewrite → IHn'. reflexivity. Qed. • 複雑 →人間は理解が大変 • Coqの問題ではない 16 非形式的証明の例 定理: 任意の n, m, p について n + (m + p) = (n + m) + p である. 証明: n についての帰納法を行う. • n = 0 とする.+ の定義より 0 + (m + p) = (0 + m) + p である. • n = S n' として n' + (m + p) = (n' + m) + p を帰 納法の仮定とする.+ の定義と帰納法の仮定よ り (S n') + (m + p) = ((S n') + m) + p は, S (n' + (m + p)) = S ((n' + m) + p) に変形できる. ☐ 17 リスト 〜構造化データの処理〜 18 自然数の組 例: Inductive による型定義 • 引数なし: true, O • 引数1つ: S • 引数2つ: Inductive natprod : Type := pair : nat → nat → natprod. 2引数に適用,またその方法でのみ構成 (コンストラクト) 19 要素の取り出し first Definition fst (p : natprod) : nat := match p with | pair x y => x end. second Definition snd (p : natprod) : nat := match p with | pair x y => y end. Eval simpl in (fst (pair 3 5)). (* ===> 3 *) 20 pair x y を (x,y) と表記する Notation "( x , y )" := (pair x y). Definition fst' (p : natprod) : nat := match p with | (x,y) => x end. パターン Definition swap_pair (p : natprod) : natprod := match p with | (x,y) => (y,x) end. 式 21 組の性質の証明 Theorem surjective_pairing' : ∀(n m : nat), (n,m) = (fst (n,m), snd (n,m)). Proof. reflexivity. Qed. より自然な表現の場合... Theorem surjective_pairing : ∀(p : natprod), p = (fst p, snd p). Proof. intros p. destruct p as (n,m). simpl. reflexivity. Qed. 置き換えを 行う 22 自然数のリスト cons 1 (cons 3 (cons 5 nil)) 1 3 5 23 自然数のリストの 構築子(コンストラクタ) cons nat natlist 数 nil 数のリスト 24 自然数のリスト 自然数のリスト: • 空リスト,もしくは • 自然数 と 自然数のリスト の組 • 以上で構成されるものだけ Inductive natlist : Type := | nil : natlist | cons : nat → natlist → natlist. 例: Definition mylist := cons 1 (cons 2 (cons 3 nil)). 25 リスト表記 以下は同じリスト cons の中置記法 Definition mylist1 := 1 :: (2 :: (3 :: nil)). Definition mylist2 := 1 :: 2 :: 3 :: nil. Definition mylist3 := [1,2,3]. :: は右結合 列挙の表記 26 リスト処理関数(1) Fixpoint repeat (n count : nat) : natlist := match count with | O => nil | S count' => n :: (repeat n count') end. [n, n, ..., n] を返す count 個 27 リスト処理関数(2): リストの長さ Fixpoint length (l:natlist) : nat := match l with | nil => O | h :: t => S (length t) end. 28 リスト処理関数(3): リストの連結 Fixpoint app (l1 l2 : natlist) : natlist := match l1 with | nil => l2 | h :: t => h :: (app t l2) end. appの中置記法 Example test_app1: [1,2,3] ++ [4,5] = [1,2,3,4,5]. Example test_app2: nil ++ [4,5] = [4,5]. Example test_app3: [1,2,3] ++ nil = [1,2,3]. 29 リスト処理関数(4): 先頭と先頭以外のリスト Definition hd (default:nat) (l:natlist) : nat := match l with | nil => default 空リストの | h :: t => h 場合に返す値 end. Definition tail (l:natlist) : natlist := match l with | nil => nil | h :: t => t end. Example test_hd1: hd 0 [1,2,3] = 1. Example test_hd2: hd 0 [] = 0. Example test_tail: tail [1,2,3] = [2,3]. 30 リストによるバッグ(多重集合)の実現 • 集合:各要素は1回しか現れない • バッグ:各要素が複数回現れても良い • リストを用いて実装する Definition bag := natlist. 31 count v s: バッグ s 中の要素 v の出現回数 Fixpoint count (v:nat) (s:bag) : nat := match s with | [] => 0 | h :: t => match beq_nat v h with | true => S (count v t) | false => count v t end end. count 1 [1,2,3,1,4,1] 3 count 6 [1,2,3,1,4,1] 0 32 再帰は不要 sum a b: バッグ a,b の和 Definition sum : bag → bag → bag := app. count 1 (sum [1,2,3] [1,4,1]) 3 33 add v s: バッグ s に要素 v を追加 Definition add (v:nat) (s:bag) : bag := v :: s. count 1 (add 1 [1,4,1]) 3 count 5 (add 1 [1,4,1]) 0 34 member v s: バッグ s 中の要素 v の有無 Definition member (v:nat) (s:bag) : bool := blt_nat O (count v s). member 1 [1,4,1] true member 2 [1,4,1] false 35 リストに関する論証 36 単純化による証明 Theorem nil_app : ∀l:natlist, [] ++ l = l. Proof. reflexivity. Qed. 自然数のときと同様に 単純化のみでOK 37 場合分けによる証明 Theorem tl_length_pred : ∀l:natlist, pred (length l) = length (tail l). Proof. intros l. destruct l as [| n l']. Case "l = nil". reflexivity. 自然数のときと同様に Case "l = cons n l'". 場合分けが必要 reflexivity. Qed. tail nil = nil 38 リスト上の帰納法 ∀l. P(l) ⇔ • P(nil) • ∀n∀l'. P(l') ⇒ P(n :: l') こちらを証明すれば, 上が言えたことに 帰納法の仮定 (IH: Induction Hypothesis) 39 ++ の結合律 Theorem app_ass : ∀l1 l2 l3 : natlist, (l1 ++ l2) ++ l3 = l1 ++ (l2 ++ l3). Proof. intros l1 l2 l3. induction l1 as [| n l1']. Case "l1 = nil". reflexivity. Case "l1 = cons n l1'". simpl. rewrite → IHl1'. reflexivity. Qed. 40 非形式的な証明 定理 任意の l1, l2, l3 について l1 ++ (l2 ++ l3) = (l1 ++ l2) ++ l3 である l1 についての帰納法で証明する. • l1 = [] とする. ++ の定義より [] ++ (l2 ++ l3)=([] ++ l2) ++ l3 である. 41 非形式的な証明(続き) • l1 = n :: l1′ であるとする.ただし, l1′ ++ (l2 ++ l3) = (l1′ ++ l2) ++ l3 (*) であるとする. • (n::l1′) ++ (l2 ++ l3) = n:: (l1′ ++ (l2 ++ l3)) ++の定義より = n::((l1′ ++ l2) ++ l3) (*)より = (n::(l1′ ++ l2)) ++ l3 ++の定義より = ((n::l1′) ++ l2) ++ l3 ++の定義より ☐ 42 SearchAbout • 証明には,以前証明した定理を使用可 • 定理の名前を覚えるのは困難 • SearchAbout (EmacsではC-cC-aC-a, C-cC-;で結果を貼り付け) SearchAbout rev. revに関する 定理を表示 43 オプション 44 リストの n 番目の要素 (オプションなし) Fixpoint index_bad (n:nat) (l:natlist) : nat := match l with | nil => 42 (* 何か必要! *) | a :: l' => match beq_nat n O with | true => a | false => index_bad (pred n) l' end end. 45 リストの n 番目の要素 (オプションあり) Inductive natoption : Type := | Some : nat → natoption | None : natoption. Fixpoint index (n:nat) (l:natlist) : natoption := match l with | nil => None (* 何か *) | a :: l' => match beq_nat n O with | true => Some a | false => index (pred n) l' end end. 46 リストの n 番目の要素 (オプションあり) Inductive natoption : Type := | Some : nat → natoption | None : natoption. Fixpoint index' (n:nat) (l:natlist) : natoption := match l with | nil => None (* 何か *) | a :: l' => if beq_nat n O then Some a else index (pred n) l' end. 条件式 47 Example test_index1 Proof. reflexivity. Example test_index2 Proof. reflexivity. Example test_index3 Proof. reflexivity. : index 0 [4,5,6,7] = Some 4. Qed. : index 3 [4,5,6,7] = Some 7. Qed. : index 10 [4,5,6,7] = None. Qed. Definition option_elim (d : nat) (o : natoption) : nat := match o with | Some n' => n' | None => d end. 48 デフォルト値のない hd Definition hd_opt (l : natlist) : natoption := match l with | nil => None | a :: _ => Some a end. Example test_hd_opt1 : hd_opt [] = None. Proof. reflexivity. Qed. Example test_hd_opt2 : hd_opt [1] = Some 1. Proof. reflexivity. Qed. Example test_hd_opt3 : hd_opt [5,6] = Some 5. Proof. reflexivity. Qed. 49 ディクショナリー 50 データ型 dictionary Inductive dictionary : Type := | empty : dictionary | record : nat → nat dictionary キー → → dictionary. 値 51 dictionary へ キーと値 の追加 Definition insert (key value : nat) (d : dictionary) : dictionary := (record key value d). 52 dictionary へ キーと値 の追加 Fixpoint find (key : nat) (d : dictionary) : natoption := match d with | empty => None key が見つからないとき | record k v d' => if beq_nat key k then Some v key が見つかったとき else find key d' end. 53 練習問題1 Theorem dictionary_invariant1' : ∀(d : dictionary) (k v: nat), (find k (insert k v d)) = Some v. Proof. intros d k v. simpl. rewrite <- beq_nat_refl. reflexivity. Qed. 54 練習問題2 Theorem dictionary_invariant2' : ∀(d : dictionary) (m n o: nat), (beq_nat m n) = false → (find m d) = (find m (insert n o d)). Proof. intros d m n o. intros H. simpl. rewrite H. reflexivity. Qed. 55 付録 56 代数データ型 1 4 1 3 9 5 7 3 5 57
© Copyright 2024 ExpyDoc