LEAN写経 応用情報数理学特論 第10回

千葉大学 萩原先生の 応用情報数理学特論 第10回 の演習をLean4で写経してみる.

演習10-01

/- 目標1.         ℕ
                  inductive
                  zero : ℕ
                  succ : ℕ → ℕ
-/
import Mathlib.Tactic -- Lean4だとだいたいこれで色々使えるようになる(適当...)

#print Nat -- これでNatの定義が見れる.
#check Nat.zero -- Lean では 0 も自然数
#check Nat.succ -- これでNat.succの型が見れる.

open Nat
#eval zero             -- 0
#eval succ zero        -- 1 ... 0の次の数
#eval succ (succ zero) -- 2 ... 1の次の数

-- #print + -- unexpected token '+'
#check Nat.add
#print Nat.add -- Lean4 では add._main で定義されていない.

/- add m      0 := m              ... m + 0      :=m
   add m succ n := succ (add m n) ... m + succ n := succ(m + n) -/
example (m : Nat) : m + 1 = succ m := rfl -- 定義のみの場合は rfl で証明できる.
example (m : Nat) : 1 + m = succ m := rfl -- 型が違うので証明出来ない

example (m : Nat) : 1 + m = succ m := by
  rw [Nat.add_comm] -- 1 + m = m + 1

演習10-02

/- 目標1.   add_succ    ... ∀ (n m : ℕ), n + succ m = succ (n + m)
            succ_add    ... ∀ (n m : ℕ), succ n + m = succ (n + m)
-/
-- 目標2.  Nat.rec_on  
-- 目標3.  rewrite, rw
import Mathlib.Tactic -- Lean4だとだいたいこれで色々使えるようになる(適当...)

open Nat
#check @add_succ
#print add_succ
#check @succ_add
#print succ_add
#print add_one
#print one_add
example (m : Nat) : 1 + m = succ m := one_add m

-- 数学的帰納法による証明
example (m : Nat) : 1 + m = succ m := 
  Nat.recOn (motive := fun x => 1 + x = succ x) 
    m 
    (show 1 + 0 = succ 0 from rfl)
    (fun (m : Nat) (h : 1 + m = succ m) => 
    show 1 + succ m = succ (succ m) from 
    calc 1 + succ m 
      _ = succ (1 + m)  := by rw [add_succ]
      _ = succ (succ m) := by rw [h])

-- simp を使った省略版
example (m : Nat) : 1 + m = succ m := 
  Nat.recOn (motive := fun x => 1 + x = succ x) 
    m
    rfl  -- base case
    (fun m h => by simp [add_succ, h]) -- add_succ と仮定 h を使って簡約(よろしくやってもらう)

演習10-03

-- 目標1. Nat上の関数を定義する.≤ , < ... Nat上の大小関係 
import Mathlib.Tactic -- Lean4だとだいたいこれで色々使えるようになる(適当...)

open Nat

def two_pow : ℕ → ℕ
|   zero   => 1             -- 2^0 = 1
| (succ n) => 2 * two_pow n -- 2^(succ n) = 2 * 2^n

#eval two_pow 10

example (n : Nat) : two_pow (succ n) = (two_pow n) + (two_pow n) := by
  calc two_pow (succ n)
    _ = 2 * two_pow n := by rfl
    _ = (1 + 1) * two_pow n := by rfl
    _ = (1 * two_pow n) + (1 * two_pow n) := by rw [right_distrib]
    _ = (two_pow n) + (two_pow n) := by rw [one_mul]

def fib_ : ℕ → ℕ  -- Nat.fib と被るため,fib_ とした.
| zero  => 1
| 1     => 1
| (n+2) => fib_ (n+1) + fib_ n

#eval fib_ 0 -- 1
#eval fib 0  -- 0 Nat.fibだと0になる.
#eval fib_ 1 -- 1
#eval fib_ 2 -- 2

演習10-04

-- 目標1. ≤ , < ... Nat上の大小関係 
-- 目標2. 定理を眺める
import Mathlib.Tactic -- Lean4だとだいたいこれで色々使えるようになる(適当...)

open Nat

#check zero_le -- 0 ≤ n
#check le_zero -- n ≤ 0 → n = 0
#check lt_succ_self -- n < succ n
#check le_succ -- n ≤ succ n
#check lt_of_lt_of_le -- n < m → m ≤ k → n < k
#check lt_of_le_of_lt -- n ≤ m → m < k → n < k
#check le_of_lt -- n < m → n ≤ m
#check lt_trans -- n < m → m < k → n < k
#check le_trans -- n ≤ m → m ≤ k → n ≤ k
#check le_refl -- n ≤ n
#check le_antisymm -- a = b
#check le_antisymm_iff -- a = b ↔ a ≤ b ∧ b ≤ a
#check le_total -- a ≤ b ∨ b ≤ a
#check succ_le_succ -- m ≤ n → succ m ≤ succ n

レポート課題

/- 
課題:
参考文献の次のExerciseを解きなさい
 ・12.5節のExercie2番
 ・14.4節のExercise4番、
 ・18.3節のExercise 1.a、1.b、2.b、2.d
-/
import Mathlib.Tactic -- Lean4だとだいたいこれで色々使えるようになる(適当...)

-- 12.5 Exercise 2
section
  open Set
  variable {U : Type}

  /- defining "disjoint" -/

  def disj (A B : Set U) : Prop := ∀ ⦃x⦄, x ∈ A → x ∈ B → False

  example (A B : Set U) (h : ∀ x, ¬ (x ∈ A ∧ x ∈ B)) : disj A B := by
  intro x
  intro (h1 : x ∈ A)
  intro (h2 : x ∈ B)
  obtain (h3 : x ∈ A ∧ x ∈ B) := And.intro h1 h2
  exact h x h3
  
  -- notice that we do not have to mention x when applying
  --   h : disj A B
  example (A B : Set U) (h1 : disj A B) (x : U)
      (h2 : x ∈ A) (h3 : x ∈ B) :
    False := h1 h2 h3

  -- the same is true of ⊆
  example (A B : Set U) (x : U) (h : A ⊆ B) (h1 : x ∈ A) :
    x ∈ B := h h1

  example (A B C D : Set U) (h1 : disj A B) (h2 : C ⊆ A) 
    (h3 : D ⊆ B) : disj C D := by
    intro x hC hD
    have hA : x ∈ A := h2 hC
    have hB : x ∈ B := h3 hD
    exact h1 hA hB
end

-- 14.4 Exercise 4
section
  open Nat
  example : 1 ≤ 4 := by
  calc
    1 ≤ 2 := le_succ 1
    _ ≤ 3 := le_succ 2
    _ ≤ 4 := le_succ 3
end

-- 18.3 Exercise 1.a 1.b 2.b 2.d
section
  open Nat

  --1.a.
  example : ∀ m n k : Nat, m * (n + k) = m * n + m * k := left_distrib

  --1.b.
  example : ∀ n : Nat, 0 * n = 0 := zero_mul

  --2.b.
  #check Nat.sub_le_sub_right
  example : ∀ m n k : Nat, n + k ≤ m + k → n ≤ m := by
    intro m n k
    intro h
    have h1 : n + k - k ≤ m + k - k := by
      apply Nat.sub_le_sub_right h k
    simp at h1 -- n ≤ m にする.
    exact h1

  --2.d.
  example : ∀ m n : Nat, m ≥ n → (m = n) ∨ (m ≥ n+1) := by
    intro m n h
    cases Nat.eq_or_lt_of_le h with
    | inl heq => -- 仮定の等式を使って goal の等式(左側)を証明する.
        replace heq : m = n := Eq.symm heq
        left
        exact heq
    | inr hlt => -- 仮定の不等式 < を使って goal の不等式(右側)を証明する.
        right
        exact hlt
      
  #check Nat.eq_or_lt_of_le -- ≤ を = ∨ < に分解する. 
end

Posted

in

by

Tags:

Comments

Leave a Reply

Your email address will not be published. Required fields are marked *