Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

全射/単射の分裂 #884

Merged
merged 1 commit into from
Sep 24, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
123 changes: 123 additions & 0 deletions Examples/Solution/InverseSurjInj.lean
Original file line number Diff line number Diff line change
@@ -0,0 +1,123 @@
/- # 全射・単射と左逆・右逆写像

関数 `f : A → B` が**全射**であるとは、任意の `b : B` に対して `f a = b` となる `a : A` が存在することをいいます。また、`f` が**単射**であるとは、任意の `a₁, a₂ : A` に対して `f a₁ = f a₂` ならば `a₁ = a₂` となることをいいます。

これを Lean で表現すると次のようになります。
-/
set_option autoImplicit false --#
set_option relaxedAutoImplicit false --#

variable {A B : Type}

/-- 関数の全射性 -/
def Function.Surjective (f : A → B) : Prop := ∀ b, ∃ a, f a = b

/-- 関数の単射性 -/
def Function.Injective (f : A → B) : Prop := ∀ {a₁ a₂ : A}, f a₁ = f a₂ → a₁ = a₂

/- 一見すると、全射と単射はペアになる概念とは思えないかもしれません。束縛変数の数も違いますし、意味上もまったく独立した概念のように見えます。

しかし、`A` が空でないと仮定すれば、選択原理 [`Classical.choice`](../Declarative/Axiom.md#ClassicalChoice) を使うことによって、全射 `f : A → B` があれば逆方向の単射 `g : B → A` が構成でき、逆に単射 `f : A → B` があれば逆方向の全射 `g : B → A` を構成することができます。

ある意味で、全射と単射はペアをなす概念であると言えるかもしれないですね。今回の演習問題のテーマはこの定理です。
-/

/- ## 問1: 全射から逆方向の単射
まずは、全射 `f : A → B` が存在すれば逆方向の単射 `g : B → A` も存在することを示しましょう。

実際にはより強く、`f ∘ g = id` を満たすような `g` が構成できます。一般に、`f ∘ g = id` が成り立つとき、`g` を `f` の右逆写像であるとか、切断(section)であるとかいいます。
-/

-- 選択原理を使用する
open Function Classical

/-- 全射 `f : A → B` があれば、選択原理を使用することにより
単射 `g : B → A` を作ることができる。-/
theorem surj_to_inj (f : A → B) (hsurj : Surjective f)
: ∃ g : B → A, Injective g := by
-- まず `g` を構成する。
-- 任意の `b : B` に対して `f` の全射性より
-- `f a = b` となる `a : A` が存在するのでそれを返す。
--##--
let g' : (b : B) → {a : A // f a = b} := fun b =>
have h : ∃ a, f a = b := hsurj b
⟨Classical.choose h, Classical.choose_spec h⟩
--##--
let g : B → A := fun b => /- sorry -/ (g' b).val

-- `g` の定義と `f` の全射性から、`f (g b) = b` が成り立つ。
have gdef : ∀ b, f (g b) = b := by
-- sorry
intro b
rw [show g b = (g' b).val from rfl]
simp_all [(g' b).property]
-- sorry

-- `g` が単射であることを示したい。
-- それには、`f ∘ g = id` を示せば十分。
suffices ∀ b, f (g b) = b from by
-- sorry
exists g
intro b₁ b₂ h
replace h : b₁ = b₂ := calc
_ = f (g b₁) := by rw [this]
_ = f (g b₂) := by rw [h]
_ = _ := by rw [this]
exact h
-- sorry

-- 後は `f ∘ g = id` を示せば良いが、これは既に示した。
exact gdef

/- ## 問2: 単射から逆方向の全射
次に `f : A → B` が単射であれば、逆方向の全射 `g : B → A` も存在することを示しましょう。

これも実際にはより強く、`g ∘ f = id` を満たすような `g` が構成できます。一般に、`g ∘ f = id` が成り立つとき、`g` を `f` の左逆写像であるとか、引き込み(retraction)であるとかいいます。
-/

/-- 単射 `f : A → B` があれば、選択原理を使用することにより
全射 `g : B → A` を作ることができる。 -/
theorem inj_to_surj [Inhabited A] (f : A → B) (hinj : Injective f)
: ∃ g : B → A, Surjective g := by
-- まず `g` を構成する。
-- `g b` の値を構成するために、`b : B` が `f` の像に入っているかで場合分けをし、
-- 入っていなければ適当な値、入っていれば `b = f a` となる `a` を返すようにする。
let g : B → A := fun b => /- sorry -/
if h : ∃ a, f a = b then Classical.choose h --##
else default --##

-- `g` の定義と `f` の単射性から、`g (f a) = a` が成り立つ。
have gdef : ∀ a, g (f a) = a := by
-- sorry
-- `a : A` が与えられたとする。
intro a

-- `g` の定義を展開する
dsimp only [g]

-- `f a` は明らかに `f` の像に入っているということを利用して、
-- `g` の定義の中の `if` 式を簡約する。
split
case isFalse h =>
have : ∃ a₁, f a₁ = f a := ⟨a, rfl⟩
simp_all [this]

-- 後は `f` の単射性から従う。
case isTrue h =>
have := Classical.choose_spec h
apply hinj
assumption
-- sorry

-- `g` が全射であることを示したい。
-- それには、`g ∘ f = id` を示せば十分。
suffices ∀ a, g (f a) = a from by
-- sorry
exists g
intro a
exists f a
apply this
-- sorry

-- 後は `g ∘ f = id` を示せば良いが、これは既に示した。
exact gdef
80 changes: 80 additions & 0 deletions Exercise/InverseSurjInj.lean
Original file line number Diff line number Diff line change
@@ -0,0 +1,80 @@
/- # 全射・単射と左逆・右逆写像

関数 `f : A → B` が**全射**であるとは、任意の `b : B` に対して `f a = b` となる `a : A` が存在することをいいます。また、`f` が**単射**であるとは、任意の `a₁, a₂ : A` に対して `f a₁ = f a₂` ならば `a₁ = a₂` となることをいいます。

これを Lean で表現すると次のようになります。
-/
set_option autoImplicit false --#
set_option relaxedAutoImplicit false --#

variable {A B : Type}

/-- 関数の全射性 -/
def Function.Surjective (f : A → B) : Prop := ∀ b, ∃ a, f a = b

/-- 関数の単射性 -/
def Function.Injective (f : A → B) : Prop := ∀ {a₁ a₂ : A}, f a₁ = f a₂ → a₁ = a₂

/- 一見すると、全射と単射はペアになる概念とは思えないかもしれません。束縛変数の数も違いますし、意味上もまったく独立した概念のように見えます。

しかし、`A` が空でないと仮定すれば、選択原理 [`Classical.choice`](../Declarative/Axiom.md#ClassicalChoice) を使うことによって、全射 `f : A → B` があれば逆方向の単射 `g : B → A` が構成でき、逆に単射 `f : A → B` があれば逆方向の全射 `g : B → A` を構成することができます。

ある意味で、全射と単射はペアをなす概念であると言えるかもしれないですね。今回の演習問題のテーマはこの定理です。
-/

/- ## 問1: 全射から逆方向の単射
まずは、全射 `f : A → B` が存在すれば逆方向の単射 `g : B → A` も存在することを示しましょう。

実際にはより強く、`f ∘ g = id` を満たすような `g` が構成できます。一般に、`f ∘ g = id` が成り立つとき、`g` を `f` の右逆写像であるとか、切断(section)であるとかいいます。
-/

-- 選択原理を使用する
open Function Classical

/-- 全射 `f : A → B` があれば、選択原理を使用することにより
単射 `g : B → A` を作ることができる。-/
theorem surj_to_inj (f : A → B) (hsurj : Surjective f)
: ∃ g : B → A, Injective g := by
-- まず `g` を構成する。
-- 任意の `b : B` に対して `f` の全射性より
-- `f a = b` となる `a : A` が存在するのでそれを返す。
let g : B → A := fun b => sorry

-- `g` の定義と `f` の全射性から、`f (g b) = b` が成り立つ。
have gdef : ∀ b, f (g b) = b := by
sorry

-- `g` が単射であることを示したい。
-- それには、`f ∘ g = id` を示せば十分。
suffices ∀ b, f (g b) = b from by
sorry

-- 後は `f ∘ g = id` を示せば良いが、これは既に示した。
exact gdef

/- ## 問2: 単射から逆方向の全射
次に `f : A → B` が単射であれば、逆方向の全射 `g : B → A` も存在することを示しましょう。

これも実際にはより強く、`g ∘ f = id` を満たすような `g` が構成できます。一般に、`g ∘ f = id` が成り立つとき、`g` を `f` の左逆写像であるとか、引き込み(retraction)であるとかいいます。
-/

/-- 単射 `f : A → B` があれば、選択原理を使用することにより
全射 `g : B → A` を作ることができる。 -/
theorem inj_to_surj [Inhabited A] (f : A → B) (hinj : Injective f)
: ∃ g : B → A, Surjective g := by
-- まず `g` を構成する。
-- `g b` の値を構成するために、`b : B` が `f` の像に入っているかで場合分けをし、
-- 入っていなければ適当な値、入っていれば `b = f a` となる `a` を返すようにする。
let g : B → A := fun b => sorry

-- `g` の定義と `f` の単射性から、`g (f a) = a` が成り立つ。
have gdef : ∀ a, g (f a) = a := by
sorry

-- `g` が全射であることを示したい。
-- それには、`g ∘ f = id` を示せば十分。
suffices ∀ a, g (f a) = a from by
sorry

-- 後は `g ∘ f = id` を示せば良いが、これは既に示した。
exact gdef
1 change: 1 addition & 0 deletions src/SUMMARY.md
Original file line number Diff line number Diff line change
Expand Up @@ -172,6 +172,7 @@
- [床屋のパラドクス](./Exercise/BarberParadox.md)
- [騎士と悪党のパズル](./Exercise/KnightAndKnave.md)
- [「ならば」の定義を疑う](./Exercise/DoubtImplication.md)
- [全射・単射と左逆・右逆写像](./Exercise/InverseSurjInj.md)
- [Cantorの定理](./Exercise/CantorTheorem.md)
- [Cantorの対関数の全単射性](./Exercise/CantorPairing.md)
- [Heying代数とBool代数](./Exercise/HeytingAndBooleanAlgebra.md)