/-
Copyright 2025 The Formal Conjectures Authors.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
https://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
-/modulepublicimportMathlib.Computability.TuringMachine.PostTuringMachinepublicimportMathlib.Logic.Relation@[expose]publicsectiontheoremPart.get_eq_get{σ:Type*}{ab:Partσ}(ha:a.Dom)(hb:a.getha∈b):a=b:=σ:Type u_1a:Partσb:Partσha:a.Domhb:a.getha∈b⊢ a=bσ:Type u_1a:Partσb:Partσha:a.Domhb:a.getha∈bhb':b.Dom⊢ a=brwa[σ:Type u_1a:Partσb:Partσha:a.Domhb':b.Domhb:a.getha=b.gethb'⊢ a=bσ:Type u_1a:Partσb:Partσha:a.Domhb':b.Domhb:a=b⊢ a=bσ:Type u_1a:Partσb:Partσha:a.Domhb':b.Domhb:a=b⊢ a=bathbnamespaceStateTransitionlemmadom_of_apply_eq_none{σ:Type*}{f:σ→Optionσ}{s:σ}(hf:fs=none):s∈evalfs:=σ:Type u_1f:σ→Optionσs:σhf:fs=none⊢ s∈evalfsσ:Type u_1f:σ→Optionσs:σhf:fs=none⊢ Sum.inls∈Part.some((fs).elim(Sum.inls)Sum.inr)All goals completed! 🐙σ:Type u_1f:σ→Optionσs:σH:(evalfs).Domthis:Reachesfs((evalfs).getH)∧f((evalfs).getH)=none⊢ f((evalfs).getH)=noneexactthis.rightAll goals completed! 🐙-- TODO(Paul-Lez): also prove this for `PFun.fix`/golf using the `PFun.fix` APItheoremeval_get_eval{σ:Type*}{f:σ→Optionσ}{s:σ}(H:(evalfs).Dom):evalf((evalfs).getH)=evalfs:=byσ:Type u_1f:σ→Optionσs:σH:(evalfs).Dom⊢ evalf((evalfs).getH)=evalfssymmσ:Type u_1f:σ→Optionσs:σH:(evalfs).Dom⊢ evalfs=evalf((evalfs).getH)applyPart.get_eq_getH(dom_of_apply_eq_none?_)σ:Type u_1f:σ→Optionσs:σH:(evalfs).Dom⊢ f((evalfs).getH)=nonesimp[apply_get_eval]All goals completed! 🐙-- TODO(Paul-Lez): also prove this for `PFun.fix`/golf using the `PFun.fix` APItheoremeval_eq_eval{σ:Type*}{f:σ→Optionσ}{aa':σ}(H:fa=somea'):evalfa=evalfa':=byσ:Type u_1f:σ→Optionσa:σa':σH:fa=somea'⊢ evalfa=evalfa'applyreaches_evalσ:Type u_1f:σ→Optionσa:σa':σH:fa=somea'⊢ Reachesfaa'applyRelation.ReflTransGen.singleσ:Type u_1f:σ→Optionσa:σa':σH:fa=somea'⊢ a'∈farw[Hσ:Type u_1f:σ→Optionσa:σa':σH:fa=somea'⊢ a'∈somea'σ:Type u_1f:σ→Optionσa:σa':σH:fa=somea'⊢ a'∈somea']σ:Type u_1f:σ→Optionσa:σa':σH:fa=somea'⊢ a'∈somea'rflAll goals completed! 🐙-- TODO(lezeau): this should be generalized to `PFun.fix`theoremeval_dom_iff{σ:Type*}{f:σ→Optionσ}{s:σ}:(∃n,((Option.bind·f)^[n+1]s)=none)↔(evalfs).Dom:=byσ:Type u_1f:σ→Optionσs:σ⊢ (∃n,(funx↦x.bindf)^[n+1](somes)=none)↔(evalfs).Domrefine⟨fun⟨n,hn⟩↦?_,funH↦?_⟩refine_1σ:Type u_1f:σ→Optionσs:σx✝:∃n,(funx↦x.bindf)^[n+1](somes)=nonen:ℕhn:(funx↦x.bindf)^[n+1](somes)=none⊢ (evalfs).Domrefine_2σ:Type u_1f:σ→Optionσs:σH:(evalfs).Dom⊢ ∃n,(funx↦x.bindf)^[n+1](somes)=none·refine_1σ:Type u_1f:σ→Optionσs:σx✝:∃n,(funx↦x.bindf)^[n+1](somes)=nonen:ℕhn:(funx↦x.bindf)^[n+1](somes)=none⊢ (evalfs).Dominductionngeneralizingswith|zero=>refine_1.zeroσ:Type u_1f:σ→Optionσs:σx✝:∃n,(funx↦x.bindf)^[n+1](somes)=nonehn:(funx↦x.bindf)^[0+1](somes)=none⊢ (evalfs).Domrw[zero_add,refine_1.zeroσ:Type u_1f:σ→Optionσs:σx✝:∃n,(funx↦x.bindf)^[n+1](somes)=nonehn:(funx↦x.bindf)^[1](somes)=none⊢ (evalfs).Domrefine_1.zeroσ:Type u_1f:σ→Optionσs:σx✝:∃n,(funx↦x.bindf)^[n+1](somes)=nonehn:fs=none⊢ (evalfs).DomFunction.iterate_one,refine_1.zeroσ:Type u_1f:σ→Optionσs:σx✝:∃n,(funx↦x.bindf)^[n+1](somes)=nonehn:(somes).bindf=none⊢ (evalfs).Domrefine_1.zeroσ:Type u_1f:σ→Optionσs:σx✝:∃n,(funx↦x.bindf)^[n+1](somes)=nonehn:fs=none⊢ (evalfs).DomOption.bind_somerefine_1.zeroσ:Type u_1f:σ→Optionσs:σx✝:∃n,(funx↦x.bindf)^[n+1](somes)=nonehn:fs=none⊢ (evalfs).Domrefine_1.zeroσ:Type u_1f:σ→Optionσs:σx✝:∃n,(funx↦x.bindf)^[n+1](somes)=nonehn:fs=none⊢ (evalfs).Dom]athnrefine_1.zeroσ:Type u_1f:σ→Optionσs:σx✝:∃n,(funx↦x.bindf)^[n+1](somes)=nonehn:fs=none⊢ (evalfs).Domsimpa[Part.dom_iff_mem]using⟨s,dom_of_apply_eq_nonehn⟩All goals completed! 🐙|succnih=>refine_1.succσ:Type u_1f:σ→Optionσn:ℕih:∀{s:σ},(∃n,(funx↦x.bindf)^[n+1](somes)=none)→(funx↦x.bindf)^[n+1](somes)=none→(evalfs).Doms:σx✝:∃n,(funx↦x.bindf)^[n+1](somes)=nonehn:(funx↦x.bindf)^[n+1+1](somes)=none⊢ (evalfs).Domobtainha|⟨a',ha'⟩:=(fs).eq_none_or_eq_somerefine_1.succ.inlσ:Type u_1f:σ→Optionσn:ℕih:∀{s:σ},(∃n,(funx↦x.bindf)^[n+1](somes)=none)→(funx↦x.bindf)^[n+1](somes)=none→(evalfs).Doms:σx✝:∃n,(funx↦x.bindf)^[n+1](somes)=nonehn:(funx↦x.bindf)^[n+1+1](somes)=noneha:fs=none⊢ (evalfs).Domrefine_1.succ.inrσ:Type u_1f:σ→Optionσn:ℕih:∀{s:σ},(∃n,(funx↦x.bindf)^[n+1](somes)=none)→(funx↦x.bindf)^[n+1](somes)=none→(evalfs).Doms:σx✝:∃n,(funx↦x.bindf)^[n+1](somes)=nonehn:(funx↦x.bindf)^[n+1+1](somes)=nonea':σha':fs=somea'⊢ (evalfs).Dom·refine_1.succ.inlσ:Type u_1f:σ→Optionσn:ℕih:∀{s:σ},(∃n,(funx↦x.bindf)^[n+1](somes)=none)→(funx↦x.bindf)^[n+1](somes)=none→(evalfs).Doms:σx✝:∃n,(funx↦x.bindf)^[n+1](somes)=nonehn:(funx↦x.bindf)^[n+1+1](somes)=noneha:fs=none⊢ (evalfs).Domsimpa[Part.dom_iff_mem]using⟨s,dom_of_apply_eq_noneha⟩All goals completed! 🐙·refine_1.succ.inrσ:Type u_1f:σ→Optionσn:ℕih:∀{s:σ},(∃n,(funx↦x.bindf)^[n+1](somes)=none)→(funx↦x.bindf)^[n+1](somes)=none→(evalfs).Doms:σx✝:∃n,(funx↦x.bindf)^[n+1](somes)=nonehn:(funx↦x.bindf)^[n+1+1](somes)=nonea':σha':fs=somea'⊢ (evalfs).Domsimp_rw[refine_1.succ.inrσ:Type u_1f:σ→Optionσn:ℕih:∀{s:σ},(∃n,(funx↦x.bindf)^[n+1](somes)=none)→(funx↦x.bindf)^[n+1](somes)=none→(evalfs).Doms:σx✝:∃n,(funx↦x.bindf)^[n+1](somes)=nonehn:(funx↦x.bindf)^[n+1+1](somes)=nonea':σha':fs=somea'⊢ (evalfs).DomFunction.iterate_succ,refine_1.succ.inrσ:Type u_1f:σ→Optionσn:ℕih:∀{s:σ},(∃n,((funx↦x.bindf)^[n]∘funx↦x.bindf)(somes)=none)→((funx↦x.bindf)^[n]∘funx↦x.bindf)(somes)=none→(evalfs).Doms:σx✝:∃n,(funx↦x.bindf)^[n+1](somes)=nonehn:(((funx↦x.bindf)^[n]∘funx↦x.bindf)∘funx↦x.bindf)(somes)=nonea':σha':fs=somea'⊢ (evalfs).DomFunction.comp_apply,refine_1.succ.inrσ:Type u_1f:σ→Optionσn:ℕih:∀{s:σ},(∃n,(funx↦x.bindf)^[n]((somes).bindf)=none)→(funx↦x.bindf)^[n]((somes).bindf)=none→(evalfs).Doms:σx✝:∃n,(funx↦x.bindf)^[n+1](somes)=nonehn:(funx↦x.bindf)^[n](((somes).bindf).bindf)=nonea':σha':fs=somea'⊢ (evalfs).DomOption.bind_somerefine_1.succ.inrσ:Type u_1f:σ→Optionσn:ℕih:∀{s:σ},(∃n,(funx↦x.bindf)^[n](fs)=none)→(funx↦x.bindf)^[n](fs)=none→(evalfs).Doms:σx✝:∃n,(funx↦x.bindf)^[n+1](somes)=nonehn:(funx↦x.bindf)^[n]((fs).bindf)=nonea':σha':fs=somea'⊢ (evalfs).Dom]athnihsimp_rw[refine_1.succ.inrσ:Type u_1f:σ→Optionσn:ℕih:∀{s:σ},(∃n,(funx↦x.bindf)^[n](fs)=none)→(funx↦x.bindf)^[n](fs)=none→(evalfs).Doms:σx✝:∃n,(funx↦x.bindf)^[n+1](somes)=nonehn:(funx↦x.bindf)^[n]((fs).bindf)=nonea':σha':fs=somea'⊢ (evalfs).Domha',refine_1.succ.inrσ:Type u_1f:σ→Optionσn:ℕih:∀{s:σ},(∃n,(funx↦x.bindf)^[n](fs)=none)→(funx↦x.bindf)^[n](fs)=none→(evalfs).Doms:σx✝:∃n,(funx↦x.bindf)^[n+1](somes)=nonea':σha':fs=somea'hn:(funx↦x.bindf)^[n]((somea').bindfuna↦fa)=none⊢ (evalfs).DomOption.bind_somerefine_1.succ.inrσ:Type u_1f:σ→Optionσn:ℕih:∀{s:σ},(∃n,(funx↦x.bindf)^[n](fs)=none)→(funx↦x.bindf)^[n](fs)=none→(evalfs).Doms:σx✝:∃n,(funx↦x.bindf)^[n+1](somes)=nonea':σha':fs=somea'hn:(funx↦x.bindf)^[n](fa')=none⊢ (evalfs).Dom]athnhaveih:=@iha'⟨n,hn⟩hnrefine_1.succ.inrσ:Type u_1f:σ→Optionσn:ℕih✝:∀{s:σ},(∃n,(funx↦x.bindf)^[n](fs)=none)→(funx↦x.bindf)^[n](fs)=none→(evalfs).Doms:σx✝:∃n,(funx↦x.bindf)^[n+1](somes)=nonea':σha':fs=somea'hn:(funx↦x.bindf)^[n](fa')=noneih:(evalfa').Dom⊢ (evalfs).Domrwa[eval_eq_evalha'refine_1.succ.inrσ:Type u_1f:σ→Optionσn:ℕih✝:∀{s:σ},(∃n,(funx↦x.bindf)^[n](fs)=none)→(funx↦x.bindf)^[n](fs)=none→(evalfs).Doms:σx✝:∃n,(funx↦x.bindf)^[n+1](somes)=nonea':σha':fs=somea'hn:(funx↦x.bindf)^[n](fa')=noneih:(evalfa').Dom⊢ (evalfa').Dom]refine_1.succ.inrσ:Type u_1f:σ→Optionσn:ℕih✝:∀{s:σ},(∃n,(funx↦x.bindf)^[n](fs)=none)→(funx↦x.bindf)^[n](fs)=none→(evalfs).Doms:σx✝:∃n,(funx↦x.bindf)^[n+1](somes)=nonea':σha':fs=somea'hn:(funx↦x.bindf)^[n](fa')=noneih:(evalfa').Dom⊢ (evalfa').Dom·refine_2σ:Type u_1f:σ→Optionσs:σH:(evalfs).Dom⊢ ∃n,(funx↦x.bindf)^[n+1](somes)=noneletC(s):Prop:=(evalfs).Dom→∃n,(Option.bind·f)^[n+1]s=nonerefine_2σ:Type u_1f:σ→Optionσs:σH:(evalfs).DomC:σ→Prop:=funs↦(evalfs).Dom→∃n,(funx↦x.bindf)^[n+1](somes)=none⊢ ∃n,(funx↦x.bindf)^[n+1](somes)=noneapplyevalInduction(C:=C)(a:=s)(h:=Part.get_memH)_Hσ:Type u_1f:σ→Optionσs:σH:(evalfs).DomC:σ→Prop:=funs↦(evalfs).Dom→∃n,(funx↦x.bindf)^[n+1](somes)=none⊢ ∀(a:σ),(evalfs).getH∈evalfa→(∀(a':σ),fa=somea'→Ca')→CaintroahahHHσ:Type u_1f:σ→Optionσs:σH:(evalfs).DomC:σ→Prop:=funs↦(evalfs).Dom→∃n,(funx↦x.bindf)^[n+1](somes)=nonea:σha:(evalfs).getH∈evalfah:∀(a':σ),fa=somea'→Ca'HH:(evalfa).Dom⊢ ∃n,(funx↦x.bindf)^[n+1](somea)=noneobtainha|⟨a',ha'⟩:=(fa).eq_none_or_eq_someinlσ:Type u_1f:σ→Optionσs:σH:(evalfs).DomC:σ→Prop:=funs↦(evalfs).Dom→∃n,(funx↦x.bindf)^[n+1](somes)=nonea:σha✝:(evalfs).getH∈evalfah:∀(a':σ),fa=somea'→Ca'HH:(evalfa).Domha:fa=none⊢ ∃n,(funx↦x.bindf)^[n+1](somea)=noneinrσ:Type u_1f:σ→Optionσs:σH:(evalfs).DomC:σ→Prop:=funs↦(evalfs).Dom→∃n,(funx↦x.bindf)^[n+1](somes)=nonea:σha:(evalfs).getH∈evalfah:∀(a':σ),fa=somea'→Ca'HH:(evalfa).Doma':σha':fa=somea'⊢ ∃n,(funx↦x.bindf)^[n+1](somea)=none·inlσ:Type u_1f:σ→Optionσs:σH:(evalfs).DomC:σ→Prop:=funs↦(evalfs).Dom→∃n,(funx↦x.bindf)^[n+1](somes)=nonea:σha✝:(evalfs).getH∈evalfah:∀(a':σ),fa=somea'→Ca'HH:(evalfa).Domha:fa=none⊢ ∃n,(funx↦x.bindf)^[n+1](somea)=noneuse0hσ:Type u_1f:σ→Optionσs:σH:(evalfs).DomC:σ→Prop:=funs↦(evalfs).Dom→∃n,(funx↦x.bindf)^[n+1](somes)=nonea:σha✝:(evalfs).getH∈evalfah:∀(a':σ),fa=somea'→Ca'HH:(evalfa).Domha:fa=none⊢ (funx↦x.bindf)^[0+1](somea)=nonesimp[ha]All goals completed! 🐙·inrσ:Type u_1f:σ→Optionσs:σH:(evalfs).DomC:σ→Prop:=funs↦(evalfs).Dom→∃n,(funx↦x.bindf)^[n+1](somes)=nonea:σha:(evalfs).getH∈evalfah:∀(a':σ),fa=somea'→Ca'HH:(evalfa).Doma':σha':fa=somea'⊢ ∃n,(funx↦x.bindf)^[n+1](somea)=noneobtain⟨n,hn⟩:=ha'ha'(byσ:Type u_1f:σ→Optionσs:σH:(evalfs).DomC:σ→Prop:=funs↦(evalfs).Dom→∃n,(funx↦x.bindf)^[n+1](somes)=nonea:σha:(evalfs).getH∈evalfah:∀(a':σ),fa=somea'→Ca'HH:(evalfa).Doma':σha':fa=somea'⊢ (evalfa').Dominrσ:Type u_1f:σ→Optionσs:σH:(evalfs).DomC:σ→Prop:=funs↦(evalfs).Dom→∃n,(funx↦x.bindf)^[n+1](somes)=nonea:σha:(evalfs).getH∈evalfah:∀(a':σ),fa=somea'→Ca'HH:(evalfa).Doma':σha':fa=somea'n:ℕhn:(funx↦x.bindf)^[n+1](somea')=none⊢ ∃n,(funx↦x.bindf)^[n+1](somea)=nonerwa[←eval_eq_evalha'σ:Type u_1f:σ→Optionσs:σH:(evalfs).DomC:σ→Prop:=funs↦(evalfs).Dom→∃n,(funx↦x.bindf)^[n+1](somes)=nonea:σha:(evalfs).getH∈evalfah:∀(a':σ),fa=somea'→Ca'HH:(evalfa).Doma':σha':fa=somea'⊢ (evalfa).Dominrσ:Type u_1f:σ→Optionσs:σH:(evalfs).DomC:σ→Prop:=funs↦(evalfs).Dom→∃n,(funx↦x.bindf)^[n+1](somes)=nonea:σha:(evalfs).getH∈evalfah:∀(a':σ),fa=somea'→Ca'HH:(evalfa).Doma':σha':fa=somea'n:ℕhn:(funx↦x.bindf)^[n+1](somea')=none⊢ ∃n,(funx↦x.bindf)^[n+1](somea)=none]σ:Type u_1f:σ→Optionσs:σH:(evalfs).DomC:σ→Prop:=funs↦(evalfs).Dom→∃n,(funx↦x.bindf)^[n+1](somes)=nonea:σha:(evalfs).getH∈evalfah:∀(a':σ),fa=somea'→Ca'HH:(evalfa).Doma':σha':fa=somea'⊢ (evalfa).Dominrσ:Type u_1f:σ→Optionσs:σH:(evalfs).DomC:σ→Prop:=funs↦(evalfs).Dom→∃n,(funx↦x.bindf)^[n+1](somes)=nonea:σha:(evalfs).getH∈evalfah:∀(a':σ),fa=somea'→Ca'HH:(evalfa).Doma':σha':fa=somea'n:ℕhn:(funx↦x.bindf)^[n+1](somea')=none⊢ ∃n,(funx↦x.bindf)^[n+1](somea)=none)inrσ:Type u_1f:σ→Optionσs:σH:(evalfs).DomC:σ→Prop:=funs↦(evalfs).Dom→∃n,(funx↦x.bindf)^[n+1](somes)=nonea:σha:(evalfs).getH∈evalfah:∀(a':σ),fa=somea'→Ca'HH:(evalfa).Doma':σha':fa=somea'n:ℕhn:(funx↦x.bindf)^[n+1](somea')=none⊢ ∃n,(funx↦x.bindf)^[n+1](somea)=noneusen+1hσ:Type u_1f:σ→Optionσs:σH:(evalfs).DomC:σ→Prop:=funs↦(evalfs).Dom→∃n,(funx↦x.bindf)^[n+1](somes)=nonea:σha:(evalfs).getH∈evalfah:∀(a':σ),fa=somea'→Ca'HH:(evalfa).Doma':σha':fa=somea'n:ℕhn:(funx↦x.bindf)^[n+1](somea')=none⊢ (funx↦x.bindf)^[n+1+1](somea)=nonesimponly[Function.iterate_succ,Function.comp_apply,Option.bind_some]athnhσ:Type u_1f:σ→Optionσs:σH:(evalfs).DomC:σ→Prop:=funs↦(evalfs).Dom→∃n,(funx↦x.bindf)^[n+1](somes)=nonea:σha:(evalfs).getH∈evalfah:∀(a':σ),fa=somea'→Ca'HH:(evalfa).Doma':σha':fa=somea'n:ℕhn:(funx↦x.bindf)^[n](fa')=none⊢ (funx↦x.bindf)^[n+1+1](somea)=nonesimp[ha',hn]All goals completed! 🐙endStateTransition