Real-time collaboration for Jupyter Notebooks, Linux Terminals, LaTeX, VS Code, R IDE, and more,
all in one place.
Real-time collaboration for Jupyter Notebooks, Linux Terminals, LaTeX, VS Code, R IDE, and more,
all in one place.
| Download
Try doing some basic maths questions in the Lean Theorem Prover. Functions, real numbers, equivalence relations and groups. Click on README.md and then on "Open in CoCalc with one click".
Project: Xena
Views: 18536License: APACHE
/- Copyright (c) 2018 Johannes Hölzl. All rights reserved. Released under Apache 2.0 license as described in the file LICENSE. Authors: Johannes Hölzl Transitive reflexive as well as reflexive closure of relations. -/ import tactic.basic logic.relator variables {α : Type*} {β : Type*} {γ : Type*} {δ : Type*} namespace relation section comp variables {r : α → β → Prop} {p : β → γ → Prop} {q : γ → δ → Prop} def comp (r : α → β → Prop) (p : β → γ → Prop) (a : α) (c : γ) : Prop := ∃b, r a b ∧ p b c local infixr ` ∘r ` : 80 := relation.comp lemma comp_eq : r ∘r (=) = r := funext $ assume a, funext $ assume b, propext $ iff.intro (assume ⟨c, h, eq⟩, eq ▸ h) (assume h, ⟨b, h, rfl⟩) lemma eq_comp : (=) ∘r r = r := funext $ assume a, funext $ assume b, propext $ iff.intro (assume ⟨c, eq, h⟩, eq.symm ▸ h) (assume h, ⟨a, rfl, h⟩) lemma iff_comp {r : Prop → α → Prop} : (↔) ∘r r = r := have (↔) = (=), by funext a b; exact iff_eq_eq, by rw [this, eq_comp] lemma comp_iff {r : α → Prop → Prop} : r ∘r (↔) = r := have (↔) = (=), by funext a b; exact iff_eq_eq, by rw [this, comp_eq] lemma comp_assoc : (r ∘r p) ∘r q = r ∘r p ∘r q := begin funext a d, apply propext, split, exact assume ⟨c, ⟨b, hab, hbc⟩, hcd⟩, ⟨b, hab, c, hbc, hcd⟩, exact assume ⟨b, hab, c, hbc, hcd⟩, ⟨c, ⟨b, hab, hbc⟩, hcd⟩ end lemma flip_comp : flip (r ∘r p) = (flip p) ∘r (flip r) := begin funext c a, apply propext, split, exact assume ⟨b, hab, hbc⟩, ⟨b, hbc, hab⟩, exact assume ⟨b, hbc, hab⟩, ⟨b, hab, hbc⟩ end end comp protected def map (r : α → β → Prop) (f : α → γ) (g : β → δ) : γ → δ → Prop := λc d, ∃a b, r a b ∧ f a = c ∧ g b = d variables {r : α → α → Prop} {a b c d : α} /-- `refl_trans_gen r`: reflexive transitive closure of `r` -/ inductive refl_trans_gen (r : α → α → Prop) (a : α) : α → Prop | refl {} : refl_trans_gen a | tail {b c} : refl_trans_gen b → r b c → refl_trans_gen c attribute [refl] refl_trans_gen.refl run_cmd tactic.mk_iff_of_inductive_prop `relation.refl_trans_gen `relation.refl_trans_gen.cases_tail_iff /-- `refl_gen r`: reflexive closure of `r` -/ inductive refl_gen (r : α → α → Prop) (a : α) : α → Prop | refl {} : refl_gen a | single {b} : r a b → refl_gen b run_cmd tactic.mk_iff_of_inductive_prop `relation.refl_gen `relation.refl_gen_iff /-- `trans_gen r`: transitive closure of `r` -/ inductive trans_gen (r : α → α → Prop) (a : α) : α → Prop | single {b} : r a b → trans_gen b | tail {b c} : trans_gen b → r b c → trans_gen c run_cmd tactic.mk_iff_of_inductive_prop `relation.trans_gen `relation.trans_gen_iff attribute [refl] refl_gen.refl lemma refl_gen.to_refl_trans_gen : ∀{a b}, refl_gen r a b → refl_trans_gen r a b | a _ refl_gen.refl := by refl | a b (refl_gen.single h) := refl_trans_gen.tail refl_trans_gen.refl h namespace refl_trans_gen @[trans] lemma trans (hab : refl_trans_gen r a b) (hbc : refl_trans_gen r b c) : refl_trans_gen r a c := begin induction hbc, case refl_trans_gen.refl { assumption }, case refl_trans_gen.tail : c d hbc hcd hac { exact hac.tail hcd } end lemma single (hab : r a b) : refl_trans_gen r a b := refl.tail hab lemma head (hab : r a b) (hbc : refl_trans_gen r b c) : refl_trans_gen r a c := begin induction hbc, case refl_trans_gen.refl { exact refl.tail hab }, case refl_trans_gen.tail : c d hbc hcd hac { exact hac.tail hcd } end lemma cases_tail : refl_trans_gen r a b → b = a ∨ (∃c, refl_trans_gen r a c ∧ r c b) := (cases_tail_iff r a b).1 lemma head_induction_on {P : ∀(a:α), refl_trans_gen r a b → Prop} {a : α} (h : refl_trans_gen r a b) (refl : P b refl) (head : ∀{a c} (h' : r a c) (h : refl_trans_gen r c b), P c h → P a (h.head h')) : P a h := begin induction h generalizing P, case refl_trans_gen.refl { exact refl }, case refl_trans_gen.tail : b c hab hbc ih { apply ih, show P b _, from head hbc _ refl, show ∀a a', r a a' → refl_trans_gen r a' b → P a' _ → P a _, from assume a a' hab hbc, head hab _ } end lemma trans_induction_on {P : ∀{a b : α}, refl_trans_gen r a b → Prop} {a b : α} (h : refl_trans_gen r a b) (ih₁ : ∀a, @P a a refl) (ih₂ : ∀{a b} (h : r a b), P (single h)) (ih₃ : ∀{a b c} (h₁ : refl_trans_gen r a b) (h₂ : refl_trans_gen r b c), P h₁ → P h₂ → P (h₁.trans h₂)) : P h := begin induction h, case refl_trans_gen.refl { exact ih₁ a }, case refl_trans_gen.tail : b c hab hbc ih { exact ih₃ hab (single hbc) ih (ih₂ hbc) } end lemma cases_head (h : refl_trans_gen r a b) : a = b ∨ (∃c, r a c ∧ refl_trans_gen r c b) := begin induction h using relation.refl_trans_gen.head_induction_on, { left, refl }, { right, existsi _, split; assumption } end lemma cases_head_iff : refl_trans_gen r a b ↔ a = b ∨ (∃c, r a c ∧ refl_trans_gen r c b) := begin split, { exact cases_head }, { assume h, rcases h with rfl | ⟨c, hac, hcb⟩, { refl }, { exact head hac hcb } } end lemma total_of_right_unique (U : relator.right_unique r) (ab : refl_trans_gen r a b) (ac : refl_trans_gen r a c) : refl_trans_gen r b c ∨ refl_trans_gen r c b := begin induction ab with b d ab bd IH, { exact or.inl ac }, { rcases IH with IH | IH, { rcases cases_head IH with rfl | ⟨e, be, ec⟩, { exact or.inr (single bd) }, { cases U bd be, exact or.inl ec } }, { exact or.inr (IH.tail bd) } } end end refl_trans_gen namespace trans_gen lemma to_refl {a b} (h : trans_gen r a b) : refl_trans_gen r a b := begin induction h with b h b c _ bc ab, exact refl_trans_gen.single h, exact refl_trans_gen.tail ab bc end @[trans] lemma trans_left (hab : trans_gen r a b) (hbc : refl_trans_gen r b c) : trans_gen r a c := begin induction hbc, case refl_trans_gen.refl : c hab { assumption }, case refl_trans_gen.tail : c d hbc hcd hac { exact hac.tail hcd } end @[trans] lemma trans (hab : trans_gen r a b) (hbc : trans_gen r b c) : trans_gen r a c := trans_left hab hbc.to_refl lemma head' (hab : r a b) (hbc : refl_trans_gen r b c) : trans_gen r a c := trans_left (single hab) hbc lemma tail' (hab : refl_trans_gen r a b) (hbc : r b c) : trans_gen r a c := begin induction hab generalizing c, case refl_trans_gen.refl : c hac { exact single hac }, case refl_trans_gen.tail : d b hab hdb IH { exact tail (IH hdb) hbc } end @[trans] lemma trans_right (hab : refl_trans_gen r a b) (hbc : trans_gen r b c) : trans_gen r a c := begin induction hbc, case trans_gen.single : c hbc { exact tail' hab hbc }, case trans_gen.tail : c d hbc hcd hac { exact hac.tail hcd } end lemma head (hab : r a b) (hbc : trans_gen r b c) : trans_gen r a c := head' hab hbc.to_refl lemma tail'_iff : trans_gen r a c ↔ ∃ b, refl_trans_gen r a b ∧ r b c := begin refine ⟨λ h, _, λ ⟨b, hab, hbc⟩, tail' hab hbc⟩, cases h with _ hac b _ hab hbc, { exact ⟨_, by refl, hac⟩ }, { exact ⟨_, hab.to_refl, hbc⟩ } end lemma head'_iff : trans_gen r a c ↔ ∃ b, r a b ∧ refl_trans_gen r b c := begin refine ⟨λ h, _, λ ⟨b, hab, hbc⟩, head' hab hbc⟩, induction h, case trans_gen.single : c hac { exact ⟨_, hac, by refl⟩ }, case trans_gen.tail : b c hab hbc IH { rcases IH with ⟨d, had, hdb⟩, exact ⟨_, had, hdb.tail hbc⟩ } end end trans_gen section refl_trans_gen open refl_trans_gen lemma refl_trans_gen_iff_eq (h : ∀b, ¬ r a b) : refl_trans_gen r a b ↔ b = a := by rw [cases_head_iff]; simp [h, eq_comm] lemma refl_trans_gen_iff_eq_or_trans_gen : refl_trans_gen r a b ↔ b = a ∨ trans_gen r a b := begin refine ⟨λ h, _, λ h, _⟩, { cases h with c _ hac hcb, { exact or.inl rfl }, { exact or.inr (trans_gen.tail' hac hcb) } }, { rcases h with rfl | h, {refl}, {exact h.to_refl} } end lemma refl_trans_gen_lift {p : β → β → Prop} {a b : α} (f : α → β) (h : ∀a b, r a b → p (f a) (f b)) (hab : refl_trans_gen r a b) : refl_trans_gen p (f a) (f b) := hab.trans_induction_on (assume a, refl) (assume a b, refl_trans_gen.single ∘ h _ _) (assume a b c _ _, trans) lemma refl_trans_gen_mono {p : α → α → Prop} : (∀a b, r a b → p a b) → refl_trans_gen r a b → refl_trans_gen p a b := refl_trans_gen_lift id lemma refl_trans_gen_eq_self (refl : reflexive r) (trans : transitive r) : refl_trans_gen r = r := funext $ λ a, funext $ λ b, propext $ ⟨λ h, begin induction h with b c h₁ h₂ IH, {apply refl}, exact trans IH h₂, end, single⟩ lemma reflexive_refl_trans_gen : reflexive (refl_trans_gen r) := assume a, refl lemma transitive_refl_trans_gen : transitive (refl_trans_gen r) := assume a b c, trans lemma refl_trans_gen_idem : refl_trans_gen (refl_trans_gen r) = refl_trans_gen r := refl_trans_gen_eq_self reflexive_refl_trans_gen transitive_refl_trans_gen lemma refl_trans_gen_lift' {p : β → β → Prop} {a b : α} (f : α → β) (h : ∀a b, r a b → refl_trans_gen p (f a) (f b)) (hab : refl_trans_gen r a b) : refl_trans_gen p (f a) (f b) := by simpa [refl_trans_gen_idem] using refl_trans_gen_lift f h hab lemma refl_trans_gen_closed {p : α → α → Prop} : (∀ a b, r a b → refl_trans_gen p a b) → refl_trans_gen r a b → refl_trans_gen p a b := refl_trans_gen_lift' id end refl_trans_gen def join (r : α → α → Prop) : α → α → Prop := λa b, ∃c, r a c ∧ r b c section join open refl_trans_gen refl_gen lemma church_rosser (h : ∀a b c, r a b → r a c → ∃d, refl_gen r b d ∧ refl_trans_gen r c d) (hab : refl_trans_gen r a b) (hac : refl_trans_gen r a c) : join (refl_trans_gen r) b c := begin induction hab, case refl_trans_gen.refl { exact ⟨c, hac, refl⟩ }, case refl_trans_gen.tail : d e had hde ih { clear hac had a, rcases ih with ⟨b, hdb, hcb⟩, have : ∃a, refl_trans_gen r e a ∧ refl_gen r b a, { clear hcb, induction hdb, case refl_trans_gen.refl { exact ⟨e, refl, refl_gen.single hde⟩ }, case refl_trans_gen.tail : f b hdf hfb ih { rcases ih with ⟨a, hea, hfa⟩, cases hfa with _ hfa, { exact ⟨b, hea.tail hfb, refl_gen.refl⟩ }, { rcases h _ _ _ hfb hfa with ⟨c, hbc, hac⟩, exact ⟨c, hea.trans hac, hbc⟩ } } }, rcases this with ⟨a, hea, hba⟩, cases hba with _ hba, { exact ⟨b, hea, hcb⟩ }, { exact ⟨a, hea, hcb.tail hba⟩ } } end lemma join_of_single (h : reflexive r) (hab : r a b) : join r a b := ⟨b, hab, h b⟩ lemma symmetric_join : symmetric (join r) := assume a b ⟨c, hac, hcb⟩, ⟨c, hcb, hac⟩ lemma reflexive_join (h : reflexive r) : reflexive (join r) := assume a, ⟨a, h a, h a⟩ lemma transitive_join (ht : transitive r) (h : ∀a b c, r a b → r a c → join r b c) : transitive (join r) := assume a b c ⟨x, hax, hbx⟩ ⟨y, hby, hcy⟩, let ⟨z, hxz, hyz⟩ := h b x y hbx hby in ⟨z, ht hax hxz, ht hcy hyz⟩ lemma equivalence_join (hr : reflexive r) (ht : transitive r) (h : ∀a b c, r a b → r a c → join r b c) : equivalence (join r) := ⟨reflexive_join hr, symmetric_join, transitive_join ht h⟩ lemma equivalence_join_refl_trans_gen (h : ∀a b c, r a b → r a c → ∃d, refl_gen r b d ∧ refl_trans_gen r c d) : equivalence (join (refl_trans_gen r)) := equivalence_join reflexive_refl_trans_gen transitive_refl_trans_gen (assume a b c, church_rosser h) lemma join_of_equivalence {r' : α → α → Prop} (hr : equivalence r) (h : ∀a b, r' a b → r a b) : join r' a b → r a b | ⟨c, hac, hbc⟩ := hr.2.2 (h _ _ hac) (hr.2.1 $ h _ _ hbc) lemma refl_trans_gen_of_transitive_reflexive {r' : α → α → Prop} (hr : reflexive r) (ht : transitive r) (h : ∀a b, r' a b → r a b) (h' : refl_trans_gen r' a b) : r a b := begin induction h' with b c hab hbc ih, { exact hr _ }, { exact ht ih (h _ _ hbc) } end lemma refl_trans_gen_of_equivalence {r' : α → α → Prop} (hr : equivalence r) : (∀a b, r' a b → r a b) → refl_trans_gen r' a b → r a b := refl_trans_gen_of_transitive_reflexive hr.1 hr.2.2 end join section eqv_gen lemma eqv_gen_iff_of_equivalence (h : equivalence r) : eqv_gen r a b ↔ r a b := iff.intro begin assume h, induction h, case eqv_gen.rel { assumption }, case eqv_gen.refl { exact h.1 _ }, case eqv_gen.symm { apply h.2.1, assumption }, case eqv_gen.trans : a b c _ _ hab hbc { exact h.2.2 hab hbc } end (eqv_gen.rel a b) lemma eqv_gen_mono {r p : α → α → Prop} (hrp : ∀a b, r a b → p a b) (h : eqv_gen r a b) : eqv_gen p a b := begin induction h, case eqv_gen.rel : a b h { exact eqv_gen.rel _ _ (hrp _ _ h) }, case eqv_gen.refl : { exact eqv_gen.refl _ }, case eqv_gen.symm : a b h ih { exact eqv_gen.symm _ _ ih }, case eqv_gen.trans : a b c ih1 ih2 hab hbc { exact eqv_gen.trans _ _ _ hab hbc } end end eqv_gen end relation