import Mathlib import Algebra.Terms namespace Algebra section Theories variable (𝔸 : Type) [Infinite 𝔸] [Countable 𝔸] [DecidableEq 𝔸] variable (sig : Signature) @[ext] structure Equation where vars : Type [vars_nominal : NominalSet 𝔸 vars] [vars_orbitFinite : OrbitFinite 𝔸 vars] left : Term 𝔸 sig vars right : Term 𝔸 sig vars namespace Equation instance (eq : Equation 𝔸 sig) : NominalSet 𝔸 eq.vars := eq.vars_nominal instance (eq : Equation 𝔸 sig) : OrbitFinite 𝔸 eq.vars := eq.vars_orbitFinite def HasDepth {𝔸 : Type} [Infinite 𝔸] [Countable 𝔸] [DecidableEq 𝔸] {sig : Signature} (eq : Equation 𝔸 sig) (n : β„•) : Prop := eq.left.HasDepth n ∧ eq.right.HasDepth n end Equation def UniformEquation := { eq : Equation 𝔸 sig // βˆƒ n, eq.HasDepth n } structure Theory where sig : Signature axioms : Set (UniformEquation 𝔸 sig) end Theories variable {𝔸 : Type} [Infinite 𝔸] [Countable 𝔸] [DecidableEq 𝔸] variable {sig : Signature} section Helpers def UniformEquation.mk (X : Type) [NominalSet 𝔸 X] [OrbitFinite 𝔸 X] {n : β„•} (t u : TermAtDepth 𝔸 sig X n) : UniformEquation 𝔸 sig := ⟨⟨X, t.val, u.val⟩, ⟨n, t.prop, u.prop⟩⟩ notation:50 X " ⊒ " lhs " ≣ " rhs => UniformEquation.mk X lhs rhs end Helpers section DerivableEquations inductive Derivable (T : Theory 𝔸) : (eq : UniformEquation 𝔸 T.sig) β†’ Prop | refl {X : Type} [NominalSet 𝔸 X] [OrbitFinite 𝔸 X] {x : X} : Derivable T (X ⊒ .var x ≣ .var x) | symm {X : Type} [NominalSet 𝔸 X] [OrbitFinite 𝔸 X] {m : β„•} {t u : TermAtDepth 𝔸 T.sig X m} : Derivable T (X ⊒ u ≣ t) β†’ Derivable T (X ⊒ t ≣ u) | trans {X : Type} [NominalSet 𝔸 X] [OrbitFinite 𝔸 X] {m : β„•} {t u v : TermAtDepth 𝔸 T.sig X m} : Derivable T (X ⊒ t ≣ v) β†’ Derivable T (X ⊒ v ≣ u) β†’ Derivable T (X ⊒ t ≣ u) | cong_pure {X : Type} [NominalSet 𝔸 X] [OrbitFinite 𝔸 X] {f : T.sig.pure} {m : β„•} {ts us : T.sig.pureArgs f β†’ TermAtDepth 𝔸 T.sig X m} : (βˆ€ x, Derivable T (X ⊒ ts x ≣ us x)) β†’ Derivable T (X ⊒ .pure f ts ≣ .pure f us) | cong_free {X : Type} [NominalSet 𝔸 X] [OrbitFinite 𝔸 X] {a : 𝔸} {f : T.sig.free} {m : β„•} {ts us : T.sig.freeArgs f β†’ TermAtDepth 𝔸 T.sig X m} : (βˆ€ x, Derivable T (X ⊒ ts x ≣ us x)) β†’ Derivable T (X ⊒ .free a f ts ≣ .free a f us) | cong_bound {X : Type} [NominalSet 𝔸 X] [OrbitFinite 𝔸 X] {a : 𝔸} {f : T.sig.bound} {m : β„•} {ts us : T.sig.boundArgs f β†’ TermAtDepth 𝔸 T.sig X m} : (βˆ€ x, Derivable T (X ⊒ ts x ≣ us x)) β†’ Derivable T (X ⊒ .bound a f ts ≣ .bound a f us) | ax' {X Y : Type} [NominalSet 𝔸 X] [OrbitFinite 𝔸 X] [NominalSet 𝔸 Y] [OrbitFinite 𝔸 Y] {m : β„•} {r s : TermAtDepth 𝔸 T.sig Y m} {l : β„•} {Οƒ : UniformSubstitution 𝔸 T.sig Y X l} {Ο„ : FPerm 𝔸} : ((Y ⊒ r ≣ s) ∈ T.axioms) β†’ (βˆ€ (y : Y) (Ο€ : FPerm 𝔸), Derivable T (X ⊒ Οƒ (Ο€ β€’ y) ≣ Ο€ β€’ (Οƒ y))) β†’ Derivable T (X ⊒ Οƒ.apply (Ο„ β€’ r) ≣ Οƒ.apply (Ο„ β€’ s)) | perm {X : Type} [NominalSet 𝔸 X] [OrbitFinite 𝔸 X] {a b : 𝔸} {f : T.sig.bound} {m : β„•} {ts us : T.sig.boundArgs f β†’ TermAtDepth 𝔸 T.sig X m} : a β‰  b β†’ (βˆ€ x, a # us x) β†’ (βˆ€ x, Derivable T (X ⊒ ts x ≣ βΈ¨a, bβΈ© β€’ us x)) β†’ Derivable T (X ⊒ .bound a f ts ≣ .bound b f us) def DerivableEq (T : Theory 𝔸) (X : Type) [NominalSet 𝔸 X] [OrbitFinite 𝔸 X] (n : β„•) : Rel (TermAtDepth 𝔸 T.sig X n) (TermAtDepth 𝔸 T.sig X n) := fun t u => Derivable T (X ⊒ t ≣ u) variable {X Y : Type} [NominalSet 𝔸 X] [OrbitFinite 𝔸 X] [NominalSet 𝔸 Y] [OrbitFinite 𝔸 Y] def UniformSubstitution.DerivablyEquivariant (T : Theory 𝔸) {l : β„•} (Οƒ : UniformSubstitution 𝔸 T.sig X Y l) : Prop := (βˆ€ (x : X) (Ο€ : FPerm 𝔸), Derivable T (Y ⊒ Οƒ (Ο€ β€’ x) ≣ Ο€ β€’ Οƒ x)) variable {T : Theory 𝔸} {n : β„•} /-- Restated ax' rule using DerivablyEquivariant in the premiss. -/ lemma Derivable.ax {m : β„•} {r s : TermAtDepth 𝔸 T.sig Y m} {l : β„•} {Οƒ : UniformSubstitution 𝔸 T.sig Y X l} {Ο„ : FPerm 𝔸} : ((Y ⊒ r ≣ s) ∈ T.axioms) β†’ Οƒ.DerivablyEquivariant T β†’ Derivable T (X ⊒ Οƒ.apply (Ο„ β€’ r) ≣ Οƒ.apply (Ο„ β€’ s)) := .ax' lemma Derivable.of_eq {m : β„•} {eq : UniformEquation 𝔸 T.sig} (t u : TermAtDepth 𝔸 T.sig eq.val.vars m) (ht : t.val = eq.val.left := by rfl) (hu : u.val = eq.val.right := by rfl) : Derivable T (eq.val.vars ⊒ t ≣ u) β†’ Derivable T eq := by intro hderiv have heq : (eq.val.vars ⊒ t ≣ u) = eq := by apply Subtype.eq; ext Β· rfl Β· rfl Β· rw [heq_eq_eq]; exact ht Β· rw [heq_eq_eq]; exact hu rw [← heq]; exact hderiv lemma Derivable.equivariant_substitution {l : β„•} (Οƒ : UniformSubstitution 𝔸 T.sig Y X l) : Οƒ.DerivablyEquivariant T β†’ βˆ€ {n : β„•} (t : TermAtDepth 𝔸 T.sig Y n) (Ο€ : FPerm 𝔸), Derivable T (X ⊒ Οƒ.apply (Ο€ β€’ t) ≣ Ο€ β€’ (Οƒ.apply t)) := by intro hequi n t Ο€ induction' t using TermAtDepth.induction <;> expose_names Β· apply of_eq (Οƒ (Ο€ β€’ x)) (Ο€ β€’ Οƒ x) exact hequi x Ο€ Β· apply of_eq (.pure f (Οƒ.apply ∘ (Ο€ β€’ Β·) ∘ args)) (.pure f ((Ο€ β€’ Β·) ∘ Οƒ.apply ∘ args)) apply Derivable.cong_pure exact h Β· apply of_eq (.free (Ο€ β€’ a) f (Οƒ.apply ∘ (Ο€ β€’ Β·) ∘ args)) (.free (Ο€ β€’ a) f ((Ο€ β€’ Β·) ∘ Οƒ.apply ∘ args)) apply Derivable.cong_free exact h Β· apply of_eq (.bound (Ο€ β€’ a) f (Οƒ.apply ∘ (Ο€ β€’ Β·) ∘ args)) (.bound (Ο€ β€’ a) f ((Ο€ β€’ Β·) ∘ Οƒ.apply ∘ args)) apply Derivable.cong_bound exact h lemma Derivable.equivariant {m : β„•} {t u : TermAtDepth 𝔸 T.sig X m} : βˆ€ (Ο€ : FPerm 𝔸), Derivable T (X ⊒ t ≣ u) β†’ Derivable T (X ⊒ Ο€ β€’ t ≣ Ο€ β€’ u) := by intro Ο€ let rename (Ο€ : FPerm 𝔸) (eq : UniformEquation 𝔸 T.sig) : UniformEquation 𝔸 T.sig := ⟨⟨eq.val.vars, Ο€ β€’ eq.val.left, Ο€ β€’ eq.val.right⟩, by obtain ⟨n, ⟨hn₁, hnβ‚‚βŸ©βŸ© := eq.prop let left : TermAtDepth 𝔸 T.sig eq.val.vars n := ⟨eq.val.left, hnβ‚βŸ© let right : TermAtDepth 𝔸 T.sig eq.val.vars n := ⟨eq.val.right, hnβ‚‚βŸ© use n; exact ⟨(Ο€ β€’ left).prop, (Ο€ β€’ right).prop⟩⟩ have rename_eq {Y : Type} [NominalSet 𝔸 Y] [OrbitFinite 𝔸 Y] {Ο€ : FPerm 𝔸} {k : β„•} {r s : TermAtDepth 𝔸 T.sig Y k} : rename Ο€ (Y ⊒ r ≣ s) = (Y ⊒ Ο€ β€’ r ≣ Ο€ β€’ s) := rfl suffices βˆ€ eq, Derivable T eq β†’ Derivable T (rename Ο€ eq) by exact this (X ⊒ t ≣ u) intro eq hderiv induction' hderiv <;> expose_names Β· exact .refl Β· rw [rename_eq] apply Derivable.symm exact a_ih Β· rw [rename_eq] at * apply Derivable.trans Β· exact a_ih Β· exact a_ih_1 Β· apply of_eq (TermAtDepth.pure f ((Ο€ β€’ Β·) ∘ ts)) (TermAtDepth.pure f ((Ο€ β€’ Β·) ∘ us)) apply Derivable.cong_pure exact a_ih Β· apply of_eq (TermAtDepth.free (Ο€ β€’ a) f ((Ο€ β€’ Β·) ∘ ts)) (TermAtDepth.free (Ο€ β€’ a) f ((Ο€ β€’ Β·) ∘ us)) apply Derivable.cong_free exact a_ih Β· apply of_eq (TermAtDepth.bound (Ο€ β€’ a) f ((Ο€ β€’ Β·) ∘ ts)) (TermAtDepth.bound (Ο€ β€’ a) f ((Ο€ β€’ Β·) ∘ us)) apply Derivable.cong_bound exact a_ih Β· rw [rename_eq] apply Derivable.trans (by apply Derivable.symm; apply equivariant_substitution; exact h_1) _ apply Derivable.trans _ (by apply equivariant_substitution; exact h_1) rw [← MulAction.mul_smul, ← MulAction.mul_smul] apply Derivable.ax Β· exact h Β· exact h_1 Β· apply of_eq (TermAtDepth.bound (Ο€ β€’ a) f ((Ο€ β€’ Β·) ∘ ts)) (TermAtDepth.bound (Ο€ β€’ b) f ((Ο€ β€’ Β·) ∘ us)) apply Derivable.perm Β· intro hcontra apply Ο€.val.injective at hcontra contradiction Β· intro x show Ο€ β€’ a # Ο€ β€’ (us x) rw [← Rel.equivariant 𝔸 NominalSet.IsFresh] exact h_1 x Β· intro x show Derivable T (X_1 ⊒ Ο€ β€’ ts x ≣ βΈ¨Ο€ a, Ο€ bβΈ© β€’ Ο€ β€’ us x) rw [← MulAction.mul_smul, ← FPerm.mul_swap_eq_swap_mul, MulAction.mul_smul] exact a_ih x instance DerivableEq.instEquivariant : Rel.Equivariant 𝔸 (DerivableEq T X n) := by constructor; intro t u exact Derivable.equivariant @[refl] lemma DerivableEq.refl (t : TermAtDepth 𝔸 T.sig X n) : DerivableEq T X n t t := by induction' t using TermAtDepth.induction <;> expose_names Β· apply Derivable.refl Β· apply Derivable.cong_pure; assumption Β· apply Derivable.cong_free; assumption Β· apply Derivable.cong_bound; assumption @[symm] lemma DerivableEq.symm {t u : TermAtDepth 𝔸 T.sig X n} : DerivableEq T X n u t β†’ DerivableEq T X n t u := by intro h apply Derivable.symm exact h @[trans] lemma DerivableEq.trans {t u v : TermAtDepth 𝔸 T.sig X n} : DerivableEq T X n t v β†’ DerivableEq T X n v u β†’ DerivableEq T X n t u := by intro htv hvu apply Derivable.trans Β· exact htv Β· exact hvu instance TermAtDepth.setoid : Setoid (TermAtDepth 𝔸 T.sig X n) where r := DerivableEq T X n iseqv := { refl := DerivableEq.refl symm := DerivableEq.symm trans := DerivableEq.trans } end DerivableEquations end Algebra