Open Seasawher opened 2 months ago
途中経過
良い感じに難しくてちょうどいいかもしれない
/- # Rayleigh の定理 -/
import Mathlib.Tactic
import Mathlib.Data.Real.Irrational
import Mathlib.Data.Set.Operations
set_option autoImplicit false
set_option relaxedAutoImplicit false
/-- 正の自然数全体 -/
def PosNat : Set ℕ := { n : ℕ | 0 < n }
/-- 実数 x の正の自然数倍を整数に丸めたものからなる部分集合 -/
def beatty (x : ℝ) : Set ℕ := { ⌊n * x⌋₊ | n ∈ PosNat}
/-- beatty が PosNat の分割を与えるという命題 -/
def beatty_partition (r s : ℝ) : Prop := beatty r ∪ beatty s = PosNat ∧ beatty r ∩ beatty s = ∅
variable (r s : ℝ) (rirr : Irrational r) (sirr : Irrational s) (rpos : r > 0) (spos : s > 0)
-- `variable` で宣言した変数を引数に加えるためのコマンド
include rirr sirr rpos spos
/-- レイリーの定理 -/
theorem rayleigh_mp (h : 1/r + 1/s = 1) : beatty_partition r s := by
dsimp [beatty_partition]
refine ⟨?cover, ?disjoint⟩
-- 重複がないことを示す
case disjoint =>
-- 両方の集合に属している要素があったと仮定して矛盾を示せばよい。
suffices ¬ (∃ x, x ∈ beatty r ∧ x ∈ beatty s) from by
aesop
-- `x` が両方の集合に属していると仮定する。
intro ⟨x, ⟨m, mpos, hr⟩, ⟨n, npos, hs⟩⟩
-- ヒント:この命題は使用しても良い
#check Nat.floor_eq_iff
-- 仮定から、ある自然数 `m > 0` が存在して
-- `x ≤ m * r < x + 1` が成り立つ。
replace ⟨mpos, «x≤mr», «mr<x+1»⟩ : 0 < m ∧ x ≤ m * r ∧ m * r < x + 1 := by
rw [Nat.floor_eq_iff (show 0 ≤ ↑m * r from by positivity)] at hr
simp_all [PosNat]
clear hr
-- 同様に、ある自然数 `n > 0` が存在して
-- `x ≤ n * s < x + 1` が成り立つ。
replace ⟨npos, «x≤ns», «ns<x+1»⟩ : 0 < n ∧ x ≤ n * s ∧ n * s < x + 1 := by
rw [Nat.floor_eq_iff (show 0 ≤ ↑n * s from by positivity)] at hs
simp_all [PosNat]
clear hs
-- ヒント:この命題は使用してOK
#check irrational_iff_ne_rational
-- `r` は無理数なので狭義の不等号が成り立つ
have «x<mr» : x < m * r := by
-- `x ≠ m * r` を示せば十分。
suffices ¬ (x = m * r) from by
exact lt_of_le_of_ne «x≤mr» this
-- `x = m * r` と仮定して矛盾を示そう。
intro hr
-- このとき `r = x / m` が成り立つので、
-- `r` は無理数ではないということになる。
have : ¬ Irrational r := by
replace hr : r = x / m := by field_simp [hr]
aesop
-- これは矛盾。
contradiction
-- `s` も無理数なので狭義の不等号が成り立つ
have «x<ns» : x < n * s := by
-- `x ≠ n * s` を示せば十分。
suffices ¬ (x = n * s) from by
exact lt_of_le_of_ne «x≤ns» this
-- `x = n * s` と仮定して矛盾を示そう。
intro hs
-- このとき `s = x / n` が成り立つので、
-- `s` は無理数ではないということになる。
have : ¬ Irrational s := by
replace hs : s = x / n := by field_simp [hs]
aesop
-- これは矛盾。
contradiction
-- したがって `x < m + n < x + 1` が成り立つことになる。
have ⟨left, right⟩ : (x : ℝ) < m + n ∧ m + n < (x + 1 : ℝ) := by
have left : (x : ℝ) < m + n := calc
x = x * (1/r + 1/s) := by rw [h]; simp
_ = x / r + x / s := by ring
_ < (m * r) / r + (n * s) / s := by gcongr
_ = m + n := by field_simp
have right : m + n < (x + 1 : ℝ) := calc
m + n = (m * r) / r + (n * s) / s := by field_simp
_ < (x + 1) / r + (x + 1) / s := by gcongr
_ = (x + 1) * (1 / r + 1 / s) := by ring
_ = x + 1 := by rw [h]; simp
simp_all
clear * - left right
-- `x` と `m + n` はともに自然数なので、これは矛盾である。
have : False := by
replace left : x + 1 ≤ m + n := by
norm_cast at left
replace right : m + n ≤ x := by
norm_cast at right
omega
omega
contradiction
-- どちらかの数列には必ず登場することを示す
case cover =>
sorry
beatty r ∩ beatty s = ∅
は本来示すべきことより少し弱い。集合として重複がないのではなくて、数列として重複がない。
つまり関数 n => Beatty n が単射であることの証明も必要だし、逆も成り立つからそれも必要
完成した。参考:レイリーの定理とその自然な証明
/- # Rayleigh の定理 -/
import Mathlib.Tactic
import Mathlib.Data.Real.Irrational
set_option autoImplicit false
set_option relaxedAutoImplicit false
/-- 正の自然数全体 -/
def PosNat : Set ℕ := { n : ℕ | 0 < n }
/-- 無理数は、正の自然数を掛けても自然数にならない -/
lemma irrational_of_posnat_mul {r : ℝ} (rirr : Irrational r) : ∀ m n : ℕ, m > 0 → (n : ℝ) ≠ m * r := by
-- `m > 0` と `n` が存在して `m * r = n` が成り立つと仮定する。
intro m n mpos h
-- このとき `r = n / m` が成り立つ。
have : r = n / m := by field_simp [h]
-- これは `r` が無理数であることに矛盾する。
simp [this] at rirr
/-- 実数 r の正の自然数倍を整数に丸めたものからなる部分集合 -/
def Beatty (r : ℝ) : Set ℕ := { ⌊n * r⌋₊ | n ∈ PosNat}
/-- `x ∉ Beatty r` ならば、`x = m * r` となる正の自然数は存在しない -/
lemma of_not_mem_beatty {x : ℕ} {r : ℝ} (nmem : x ∉ Beatty r) :
∀ m : ℕ, m > 0 → (x : ℝ) ≠ m * r := by
intro m mpos h
have : x ∈ Beatty r := by
exists m
simp_all [←h, PosNat]
contradiction
/-- Beatty が PosNat の分割を与えるという命題 -/
def beattyPartition (r s : ℝ) : Prop := Beatty r ∪ Beatty s = PosNat ∧ Beatty r ∩ Beatty s = ∅
/-- 自然数 `x > 0` が `r` の Beatty 数列に含まれないならば、どこかで「追い越されて」いる。
つまり、ある `m : Nat` が存在して `m * r < x` かつ `x + 1 ≤ (m + 1) * r` を満たす。 -/
lemma of_beatty_missing {x : ℕ} {r : ℝ} (xpos : x > 0) (rpos : r > 0) (nmem : x ∉ Beatty r) :
∃ m : ℕ, m * r < x ∧ x + 1 ≤ (m + 1) * r := by
-- `r > 0` なので、`m` を大きくしていくといつか必ず `m * r < x` は成り立たなくなる。
-- そこで `m * r < x` が成り立つような最大の `m` を取り、`M` とする。
let M := ⌊x / r⌋₊
-- この `M` が所望の条件を満たすことを示そう。
exists M
constructor
-- まず `M` の定義と `x` が Beatty 数列に含まれないことから
-- `M * r < x` が成り立つことを示そう。
case left =>
-- 技術的な補題として `0 ≤ x / r` が必要なので示す。
have lem : 0 ≤ x / r := by positivity
-- このとき `M * r ≤ x` が成り立つ。
have le : M * r ≤ x := calc
_ = ⌊x / r⌋₊ * r := by dsimp [M]
_ ≤ (x / r) * r := by simp_all [Nat.floor_le lem]
_ ≤ x := by field_simp
-- `x ∉ Beatty r` なので等号は成立しない。
-- したがって、`M * r < x` が成り立つ。
replace lt : M * r < x := by
-- 背理法で示す。仮に等号が成立したとする
suffices ¬ (M * r = x) from by
exact lt_of_le_of_ne le this
intro hx
-- 補題により、`M > 0` を示せばよい。
suffices M > 0 from by
have lem := @of_not_mem_beatty (x := x) (r := r) nmem M this
simp_all
-- これは `x > 0` より従う。
rify at xpos ⊢
nlinarith
exact lt
-- 次に `x + 1 ≤ (M + 1) * r` が成り立つことを示そう。
case right =>
-- 技術的な補題として `(M + 1) * r ≥ 0` が必要なので示す。
have lem : (M + 1) * r ≥ 0 := by positivity
-- M の定義から `x < (M + 1) * r` が成り立つ。
have : x < (M + 1) * r := calc
_ = (x / r) * r := by field_simp
_ < (⌊x / r⌋₊ + 1) * r := by gcongr; exact Nat.lt_floor_add_one (↑x / r)
_ = (M + 1) * r := by dsimp [M]
-- `x` は自然数なので床関数の定義により `x ≤ ⌊(M + 1) * r⌋₊` が成り立つ。
replace : x ≤ ⌊(M + 1) * r⌋₊ := calc
_ = ⌊x⌋₊ := by simp
_ = ⌊(x : ℝ)⌋₊ := by simp
_ ≤ ⌊(M + 1) * r⌋₊ := by gcongr
-- `x ∉ Beatty r` なので等号は成立しない。
replace : x < ⌊(M + 1) * r⌋₊ := by
-- 等号不成立を示せばよい。
suffices goal : ¬ (x = ⌊(M + 1) * r⌋₊) from by
exact lt_of_le_of_ne this goal
-- 仮に等号が成立したとする。
intro hx
-- このとき `x ∈ Beatty r` となる。
have mem : x ∈ Beatty r := by
exists (M + 1)
simp_all [PosNat]
-- これは矛盾である。
contradiction
-- `x` は自然数なので、`x + 1 ≤ ⌊(M + 1) * r⌋₊` が成り立つ。
replace : x + 1 ≤ ⌊(↑M + 1) * r⌋₊ := by
exact this
-- したがって示すべきことが言える。
replace : (x : ℝ) + 1 ≤ (↑M + 1) * r := calc
_ ≤ (⌊(M + 1) * r⌋₊ : ℝ) := by norm_cast at this ⊢
_ ≤ (M + 1) * r := by exact Nat.floor_le lem
exact this
-- 以降 `r, s` は正の実数であると仮定する
variable {r s : ℝ} (rpos : r > 0) (spos : s > 0)
include rpos spos
/-- `1/r + 1/s = 1` の関係にある実数は、1 より大きい -/
lemma gt_of_conjugate (h : 1/r + 1/s = 1) : r > 1 := calc
r = r * (1 / r + 1 / s) := by rw [h]; simp
_ = r / r + r / s := by ring
_ = 1 + r / s := by field_simp
_ > 1 := by linarith [show r / s > 0 from by positivity]
/-- `1/r + 1/s = 1` の関係にある実数から生成される Beatty 数列は正の自然数からなる -/
lemma beatty_in_posnat (h : 1/r + 1/s = 1) : Beatty r ⊆ PosNat := by
-- `x : Nat` が Beatty r に属していると仮定する。
-- このとき定義から、自然数 `n > 0` が存在して
-- `⌊n * r⌋₊ = x` が成り立つ。
intro x ⟨n, npos, hx⟩
dsimp [PosNat] at npos
-- このとき `n * r > 1` が成り立っている。
have : (n : ℝ) * r > 1 := calc
_ ≥ 1 * r := by gcongr; norm_cast
_ = r := by simp
_ > 1 := by exact gt_of_conjugate rpos spos h
clear h rpos spos npos
-- したがって `⌊n * r⌋₊ = x` も 1 以上であり、正の自然数である。
exact show x > 0 from calc
_ = ⌊n * r⌋₊ := by rw [hx]
_ ≥ ⌊(1 : ℝ)⌋₊ := by gcongr
_ = (1 : ℕ) := by simp
_ > 0 := by simp
/-- レイリーの定理(の弱いバージョン) -/
theorem rayleigh_mp (rirr : Irrational r) (sirr : Irrational s)
(h : 1/r + 1/s = 1) : beattyPartition r s := by
dsimp [beattyPartition]
refine ⟨?cover, ?disjoint⟩
-- 重複がないことを示す
case disjoint =>
-- 両方の集合に属している要素があったと仮定して矛盾を示せばよい。
suffices ¬ (∃ x, x ∈ Beatty r ∧ x ∈ Beatty s) from by
aesop
-- `x` が両方の集合に属していると仮定する。
intro ⟨x, ⟨m, mpos, hr⟩, ⟨n, npos, hs⟩⟩
-- 仮定から、ある自然数 `m > 0` が存在して
-- `x ≤ m * r < x + 1` が成り立つ。
replace ⟨mpos, «x≤mr», «mr<x+1»⟩ : 0 < m ∧ x ≤ m * r ∧ m * r < x + 1 := by
rw [Nat.floor_eq_iff (show 0 ≤ ↑m * r from by positivity)] at hr
simp_all [PosNat]
clear hr
-- 同様に、ある自然数 `n > 0` が存在して
-- `x ≤ n * s < x + 1` が成り立つ。
replace ⟨npos, «x≤ns», «ns<x+1»⟩ : 0 < n ∧ x ≤ n * s ∧ n * s < x + 1 := by
rw [Nat.floor_eq_iff (show 0 ≤ ↑n * s from by positivity)] at hs
simp_all [PosNat]
clear hs
-- `r` は無理数なので狭義の不等号が成り立つ
have «x<mr» : x < m * r := by
-- `x ≠ m * r` を示せば十分。
suffices (x : ℝ) ≠ m * r from by
exact lt_of_le_of_ne «x≤mr» this
-- 後は補題から従う。
have := @irrational_of_posnat_mul r rirr m x mpos
simp_all
-- 同様に `s` も無理数なので狭義の不等号が成り立つ
have «x<ns» : x < n * s := by
suffices (x : ℝ) ≠ n * s from by
exact lt_of_le_of_ne «x≤ns» this
have := @irrational_of_posnat_mul s sirr n x npos
simp_all
-- したがって `x < m + n < x + 1` が成り立つことになる。
have ⟨left, right⟩ : (x : ℝ) < m + n ∧ m + n < (x : ℝ) + 1 := by
have left : (x : ℝ) < m + n := calc
_ = x * (1/r + 1/s) := by rw [h]; simp
_ = x / r + x / s := by ring
_ < (m * r) / r + (n * s) / s := by gcongr
_ = m + n := by field_simp
have right : m + n < (x : ℝ) + 1 := calc
_ = (m * r) / r + (n * s) / s := by field_simp
_ < (x + 1) / r + (x + 1) / s := by gcongr
_ = (x + 1) * (1 / r + 1 / s) := by ring
_ = x + 1 := by rw [h]; simp
simp_all
clear * - left right
-- `x` と `m + n` はともに自然数なので、これは矛盾である。
have : False := by
norm_cast at left right
omega
contradiction
-- 全体をちょうど覆っていることを示す
case cover =>
-- `x : Nat` が与えられたとして、
-- `0 < x` と数列に登場することが同値であることを示す。
ext x
constructor <;> intro hx
-- 数列に登場する数は正の自然数であることを示したい。
case mp =>
have hr := beatty_in_posnat rpos spos h
have hs := beatty_in_posnat spos rpos (by linarith)
aesop
-- 正の自然数は数列に登場することを示したい。
case mpr =>
-- 背理法で示す。
by_contra hc
-- `x` がどちらにも登場しないと仮定して矛盾を示せばよい。
replace ⟨hr, hs⟩ : x ∉ Beatty r ∧ x ∉ Beatty s := by simp_all
clear hc
-- 補題から、ある `m, n : ℕ` が存在して
-- `m * r < x`, `x + 1 ≤ (m + 1) * r` かつ
-- `n * s < x`, `x + 1 ≤ (n + 1) * s` を満たす。
have ⟨m, mleft, mright⟩ := @of_beatty_missing x r (by simpa using hx) rpos hr
have ⟨n, nleft, nright⟩ := @of_beatty_missing x s (by simpa using hx) spos hs
clear hr hs
-- `r` は無理数なので等号は成立しない。
replace mright : x + 1 < (m + 1) * r := by
have := @irrational_of_posnat_mul r rirr (m + 1) (x + 1) (by simp)
suffices goal : ¬ (x + 1 = (m + 1) * r) from by
exact lt_of_le_of_ne mright goal
simp_all
clear rirr
-- 同様に `s` も無理数なので等号は成立しない。
replace nright : x + 1 < (n + 1) * s := by
have := @irrational_of_posnat_mul s sirr (n + 1) (x + 1) (by simp)
suffices goal : ¬ (x + 1 = (n + 1) * s) from by
exact lt_of_le_of_ne nright goal
simp_all
clear sirr
-- このとき `m + n < x` が成り立つ。
have left : m + n < (x : ℝ) := calc
_ = (m * r) / r + (n * s) / s := by field_simp
_ < x / r + x / s := by gcongr
_ = x * (1 / r + 1 / s) := by ring
_ = x := by rw [h]; simp
-- また `m + n + 1 > x` が成り立つ。
have right : m + n + 1 > (x : ℝ) := by
have : (m + 1) + (n + 1) > (x : ℝ) + 1 := calc
_ = ((m + 1) * r) / r + ((n + 1) * s) / s := by field_simp
_ > (x + 1) / r + (x + 1) / s := by gcongr
_ = (x + 1) * (1 / r + 1 / s) := by ring
_ = x + 1 := by rw [h]; simp
clear * - this
-- したがって `m + n + 1 > x` が成り立つ。
norm_cast at this ⊢
omega
clear * - left right
-- `m + n` と `x` はともに自然数なので、これは矛盾である。
have : False := by
norm_cast at left right
omega
contradiction
Mathlib にまだないのかと思いきや、あった
https://leanprover-community.github.io/mathlib4_docs/Mathlib/NumberTheory/Rayleigh.html
現状のコードは繰り返しが多すぎて演習問題にはできないので、リファクタリングが必要
無理数の定義からわりとすぐに従う上に、無理数を定義するのに必要な実数の闇にノータッチなまま話を進められそう。 しかも非自明。