import Mathlib.Data.Multiset.Basic import Mathlib.Data.Set.Finite.Basic import Mathlib.Data.Multiset.AddSub import Mathlib.Data.Multiset.Bind import Provenance.Util.ValueType variable {T: Type} [ValueType T] def Tuple (T : Type) (n: ℕ) := Fin n → T def Tuple.repr [Repr T] (t: Tuple T n) (_: ℕ) : Std.Format := let elems := (List.finRange n).map (fun (i: Fin n) => reprArg (t i)) Std.Format.bracket "[" (Std.Format.joinSep elems ", ") "]" def Tuple.cast (heq : n=m) (t: Tuple T n): Tuple T m := by subst heq exact t theorem Tuple.apply_cast {T: Type} (heq: n=m) (f: Tuple T m → α) (t: Tuple T n) : f (t.cast heq) = (@_root_.cast (Tuple T m → α) (Tuple T n → α) (by simp[heq]) f) t := by subst heq rfl theorem Tuple.cast_get {T: Type} (heq: n=m) (t: Tuple T n) (k: Fin m) : t.cast heq k = t (k.cast (Eq.symm heq)) := by subst heq rfl instance [DecidableEq T] : DecidableEq (Tuple T n) := λ t₁ t₂ => if h : ∀ k, t₁ k = t₂ k then isTrue (funext h) else isFalse (by intro h' apply h exact fun k => congrFun h' k) instance [Repr α] : Repr (Tuple α n) := ⟨Tuple.repr⟩ instance : Zero (Tuple T n) := ⟨λ _ ↦ 0⟩ instance : LT (Tuple T n) := ⟨λ a b ↦ ∃ i : Fin n, (∀ j, j < i → a j = b j) ∧ a i < b i⟩ instance : LE (Tuple T n) := ⟨λ a b ↦ a < b ∨ a = b⟩ instance [ToString T] : ToString (Tuple T n) where toString t := "(" ++ String.intercalate ", " (List.ofFn (fun i => toString (t i))) ++ ")" instance : DecidableRel (λ (t₁ t₂: Tuple T n) => t₁ = t₂) := λ f g ↦ if h : ∀ i, f i = g i then isTrue (funext h) else isFalse (fun H => h (congrFun H)) instance : DecidableRel (λ (t₁ t₂: Tuple T n) => t₁ < t₂) := λ f g ↦ if h : ∃ i : Fin n, (∀ j, j < i → f j = g j) ∧ f i < g i then isTrue (h) else isFalse (h) instance : LinearOrder (Tuple T n) where le_refl := by simp[(· ≤ ·)] le_antisymm := by simp[(· ≤ ·)] intro a b hab hba cases hab with | inl hab' => cases hba with | inl hba' => simp only[(· < ·)] at * rcases hab' with ⟨iab,hiab⟩ rcases hba' with ⟨iba,hiba⟩ by_cases h : iab=iba . rw[h] at hiab have := lt_trans hiab.right hiba.right have := lt_asymm (lt_trans hiab.right hiba.right) contradiction . by_cases h' : iab exact Eq.symm hba' | inr hab' => exact hab' le_trans := by intro a b c simp only[(· ≤ ·),(· < ·)] intro hab hbc cases hab with | inl habl => cases hbc with | inl hbcl => left rcases habl with ⟨iab,hiab⟩ rcases hbcl with ⟨ibc,hibc⟩ let i := min iab ibc use i have h : ∀ (j : Fin n), j < i → a j = c j := by intro j hj have hx := hiab.left have hy := hibc.left specialize hx j (lt_min_iff.mp hj).left specialize hy j (lt_min_iff.mp hj).right rw[hy] at hx; exact hx use h by_cases heq : iab = i . by_cases heq' : ibc = i . rw[heq] at hiab rw[heq'] at hibc exact lt_trans hiab.right hibc.right . have h' : i < ibc := lt_of_le_of_ne (min_le_right iab ibc) (ne_comm.mpr heq') have hab := hiab.right rw[heq] at hab have hbc := hibc.left i h' rw[hbc] at hab exact hab . have heq'' : ibc = i := by have choice : iab = i ∨ ibc = i := by have := min_choice iab ibc nth_rw 1 [eq_comm] at this nth_rw 2 [eq_comm] at this assumption tauto have h' : i < iab := lt_of_le_of_ne (min_le_left iab ibc) (ne_comm.mpr heq) have hbc := hibc.right rw[heq''] at hbc have hab := hiab.left i h' rw[hab] exact hbc | inr hbcr => subst hbcr left; exact habl | inr habr => subst habr exact hbc le_total := by intro a b simp only[(· ≤ ·)] by_cases heq: a=b . tauto . by_cases h: ∃ i, (∀ j < i, a j = b j) ∧ a i < b i . left;left simp only[(· < ·)] tauto . right;left simp only[(· < ·)] cases h' : Fin.find (λ j ↦ ¬ a j = b j) with | none => apply Fin.find_eq_none_iff.mp at h' simp at h' simp[funext h'] at heq | some k => use k have h'' := h' apply Fin.find_min at h' constructor . intro j hj; specialize h' hj simp at h'; simp[h'] . simp at h specialize h k have : ∀ j < k, a j = b j := by intro j hj; specialize h' hj simp at h' simp[h'] specialize h this apply lt_iff_le_and_ne.mpr constructor . assumption . apply Fin.find_eq_some_iff.mp at h'' rw[ne_comm] simp[h''.left] lt_iff_le_not_ge := by intro a b simp only[(· ≤ ·)] apply Iff.intro . intro hab constructor . tauto . simp only[(· < ·)] at * rcases hab with ⟨i, hi⟩ simp constructor . intro k h cases hki : compare k i with | eq => simp at hki rw[hki] exact le_of_lt hi.right | lt => simp[compare] at hki have := hi.left k hki simp[this] | gt => simp only[compare,compareOfLessAndEq] at hki by_cases hki' : k < i . simp[hki'] at hki . by_cases hki'' : k = i . rw[hki''] at hki simp at hki . simp[hki'] at hki have hgt : k>i := by apply le_of_not_gt at hki' apply lt_of_le_of_ne . assumption . exact fun a ↦ hki'' (id (Eq.symm a)) specialize h i hgt rw[h] at hi have hc : a i < a i := hi.right simp at hc . by_contra heq rw[heq] at hi simp at hi . intro ⟨h₁,h₂⟩ simp at h₂ have hne : a ≠ b := by rw[ne_comm]; exact h₂.right simp[hne] at h₁ exact h₁ toDecidableLE := λ a b ↦ match inferInstanceAs (Decidable (a isTrue (Or.inl h₁) | _, isTrue h₂ => isTrue (Or.inr h₂) | isFalse h₁, isFalse h₂ => isFalse ( fun h ↦ match h with | Or.inl h' => h₁ h' | Or.inr h' => h₂ h' ) def Relation (T) (arity: ℕ) := Multiset (Tuple T arity) def Relation.cast (heq: n=m) (r: Relation T n): Relation T m := by subst heq exact r def Relation.cast_eq (r: Relation T n) (s: Relation T m) (heq: n=m) : s = r.cast heq ↔ s = r.map (λ t ↦ t.cast heq) := by simp[Relation.cast, Tuple.cast] subst heq simp instance : Add (Relation T arity) := inferInstanceAs (Add (Multiset (Tuple T arity))) instance : Sub (Relation T arity) := inferInstanceAs (Sub (Multiset (Tuple T arity))) instance : HMul (Relation T a₁) (Relation T a₂) (Relation T (a₁+a₂)) where hMul r s := Multiset.map (λ ((x,y) : (Tuple T a₁)×(Tuple T a₂)) ↦ Fin.append x y ) (Multiset.product r s) instance : Zero (Relation T n) where zero := (∅: Multiset (Tuple T n)) instance : Zero ((n : ℕ) × Relation T n) where zero := ⟨0,(∅: Multiset (Tuple T 0))⟩ def Database (T) := List (String × Σ n, Relation T n) def Database.find (n: ℕ) (s: String) (d: Database T) : Option (Relation T n) := let rec f | [] => none | (s',rn)::tl => if h: n = rn.fst ∧ s=s' then some (Eq.mp (by rw[h.left]) rn.snd) else f tl f d def sortedInsert [LinearOrder α] (x : α) (l : {l : List α // List.Sorted (· ≤ ·) l}) : {l : List α // List.Sorted (· ≤ ·) l} := ⟨l.val.orderedInsert (· ≤ ·) x, List.Sorted.orderedInsert x l.val l.property⟩ instance [LinearOrder α] : @LeftCommutative α _ sortedInsert where left_comm := by intros a b l simp only [sortedInsert] simp apply @List.eq_of_perm_of_sorted α (· ≤ ·) . rw[List.perm_iff_count] intro c repeat rw[List.orderedInsert_count] by_cases hab : a=b <;> by_cases hca : c=a <;> by_cases hcb : c=b <;> simp[hab,hca,hcb,eq_comm] have : a≠c := by exact fun z ↦ hca (id (Eq.symm z)) simp[this] . exact List.Sorted.orderedInsert _ _ (List.Sorted.orderedInsert _ _ l.property) . exact List.Sorted.orderedInsert _ _ (List.Sorted.orderedInsert _ _ l.property) instance [ToString T] : ToString (Relation T n) where toString r := String.intercalate "\n" ((r.foldr sortedInsert ⟨[],by simp⟩).val.map toString) ++ "\n"