import FormalLab.Recursion.WellFounded import FormalLab.Recursion.Lattices import FormalLab.Recursion.FixedPoints import FormalLab.Recursion.CoinductivePredicates import FormalLab.Recursion.DomainTheory /-! # 全問題の解答:再帰・不動点・余帰納 ## 第26章:整礎関係・整礎帰納法・停止する一般再帰 ### 問題1:測度を設計して再帰呼出しを検査する #### ヒント 入力を自然数へ送る測度を選び、すべての再帰呼出しで狭義に減る不等式を示します。 #### 解答 リストを半分ずつ処理する関数なら測度を長さとします。空または一要素で停止し、それ以外では分割した各リストの 長さが元の長さより小さいことを証明します。辞書式再帰では `(m,n)` に辞書式順序を入れ、第一成分が減るか、 第一成分を保って第二成分が減ることを各呼出しで示します。測度の非増加では自己呼出しを排除できないので、 狭義性が必要です。 構文変換では節点数、書換え系では多重集合順序など、計算が実際に消費する資源を測度に選びます。 ### 問題2:接近可能性から帰納原理を展開する #### ヒント `Acc r x` の唯一の構成子が、すべての先行者の接近可能性を保持することを使います。 #### 解答 `Acc.intro : (∀y, r y x→Acc r y)→Acc r x` です。`Acc r x` からP xを示すには、その導出へ帰納し、 `h : ∀y,r y x→Acc r y` と各yへの帰納仮定 `P y` を得ます。整礎性 `∀x,Acc r x` があれば、局所ステップ `∀x,(∀y,r y x→P y)→P x` を任意のxへ適用して `∀x,P x` を得ます。再帰関数でも同じ導出木を辿るため、 無限下降列を作れません。 相互再帰は状態を直和へまとめ、その全体に整礎関係を定義すると一つの原理で扱えます。 ### 問題3:互除法の停止性と正しさを分離する #### ヒント 停止には剰余の減少、正しさには公約数集合の保存を使います。 #### 解答 `gcd a 0=a`、`gcd a b=gcd b (a%b)` とします。`b>0` なら `a%b y = start ∨ ∃ x, set x ∧ step x y theorem reachableStepMonotone (start : Nat) (step : Nat → Nat → Prop) : Monotone (reachableStep start step) := by intro left right included y generated rcases generated with atStart | ⟨x, member, moves⟩ · exact Or.inl atStart · exact Or.inr ⟨x, included member, moves⟩ end FormalLab.Appendix.Solutions.Chapter027Exercise003 namespace FormalLab.Appendix.Solutions.Chapter029Exercise001 open FormalLab.Recursion.CoinductivePredicates def iterate (next : A → A) : Nat → A → A | 0, state => state | time + 1, state => iterate next time (next state) theorem Always_at {A : Type} {good : A → Prop} {next : A → A} {state : A} (always : Always good next state) : ∀ time, good (iterate next time state) := by intro time induction time generalizing state with | zero => exact Always_now always | succ time inductionHypothesis => exact inductionHypothesis (Always_next always) end FormalLab.Appendix.Solutions.Chapter029Exercise001 namespace FormalLab.Appendix.Solutions.Chapter029Exercise002 open FormalLab.Recursion.CoinductivePredicates inductive Phase where | zero | one | two deriving DecidableEq def next : Phase → Phase | .zero => .one | .one => .two | .two => .zero def safe : Phase → Prop | .zero | .one => True | .two => False def invariant : Phase → Prop | .zero | .one => True | .two => False example : ¬Always safe next .zero := by intro always have afterTwo := Always_next (Always_next always) exact Always_now afterTwo end FormalLab.Appendix.Solutions.Chapter029Exercise002 namespace FormalLab.Appendix.Solutions.Chapter030Exercise002 open FormalLab.Recursion.DomainTheory example : FlatLe (none : Option Bool) (some true) := by trivial example : ¬FlatLe (some true) (some false) := by simp [FlatLe] end FormalLab.Appendix.Solutions.Chapter030Exercise002 namespace FormalLab.Appendix.Solutions.Chapter030Exercise003 open FormalLab.Recursion.DomainTheory example : factorialApproximation 3 3 = none := rfl example : factorialApproximation 4 3 = some 6 := rfl example : FlatLe (factorialApproximation 3 3) (factorialApproximation 4 3) := by trivial end FormalLab.Appendix.Solutions.Chapter030Exercise003