Paper
ProvSQL: provenance-aware query rewriting and probabilistic query evaluation are correct
28 pages · 24 marked passages · pdflatex · download PDF · lax-392996
-
Probabilistic query evaluation through provenance
For a probability assignment on a finite set of variables, a source query , a -instance and a tuple , the marginal probability that appears in the answer of on a random world of equals the probability of the annotation of in the annotated answer : . This is the paper's Theorem 12, the justification of intensional probabilistic query evaluation: evaluate the query once over Boolean-function annotations and take the probability of the resulting function.
-
Probabilistic query evaluation through provenance
For a probability assignment on a finite set of variables, a source query , a -instance and a tuple , the marginal probability that appears in the answer of on a random world of equals the probability of the annotation of in the annotated answer : . This is the paper's Theorem 12, the justification of intensional probabilistic query evaluation: evaluate the query once over Boolean-function annotations and take the probability of the resulting function.
-
Probabilistic query evaluation by the rewritten query
For a probability assignment on a finite set of variables, a -instance , a source query and a tuple , if is the query rewritten from by the rules (R1) to (R4), then : the marginal probability of is the probability of its annotation in the plain evaluation of on the composite reading of , each answer tuple read back as an annotated one. This is the paper's Corollary 13, combining the correctness of the rewriting with the theorem on probabilistic evaluation; as for the former, the paper states it with the aggregation rule (R5) included, which this submission does not cover.
-
The Personnel example, with probabilities
The paper's Example 14: each tuple of the -instance is kept with an independent probability, and (the others, unspecified in the paper, are here), and the probability that Nairobi is in the answer of is . Variables are numbered from 0 here, from 1 in the paper.
1 import Mathlib.Data.Rat.Defs 2 import Mathlib.Tactic.NormNum 3 import Lax392996.BooleanFunctions 4 import Lax392996.Databases 5 import Lax392996.AnnotatedDatabases 6 import Lax392996.RelationalAlgebra 7 import Lax392996.ProbabilisticDatabases 8 import Lax392996.PersonnelExample 9 import Lax392996.ProvenanceExample 10 … module docstring, 12 lines 23 24 namespace Lax392996.ProbabilityExample 25 26 open Lax392996.BooleanFunctions Lax392996.Databases Lax392996.AnnotatedDatabases 27 open Lax392996.RelationalAlgebra Lax392996.ProbabilisticDatabases 28 open Lax392996.PersonnelExample Lax392996.ProvenanceExample 29 30 /-- The probabilities of the tuples: `0.5`, except `0.7` for the second one. -/ 31 def P : ProbAssignment (Fin 7) where 32 prob x := if x = 1 then 7/10 else 1/2 33 prob_nonneg := by 34 intro x 35 split <;> norm_num 36 prob_le_one := by 37 intro x 38 split <;> norm_num 39 40 /-- Example 14: the probability that Nairobi is an answer is `0.35`. -/ 41 axiom nairobi_probability : 42 ProbAssignment.marginalProb P qcity instanceB !["Nairobi"] = 7/20 43 44 end Lax392996.ProbabilityExample 45 -
Relations and databases with multiset semantics
Values are drawn from a value type: a linearly ordered type with a zero, an addition, a subtraction and a multiplication, over which the arithmetic of query terms is read. A tuple of arity is a map , tuples being ordered lexicographically; a relation of arity is a finite multiset of -tuples, with multiset union and the cross product of multisets; a database is a finite list of named relations, each with its arity, looked up by name and arity.
1 import Mathlib.Algebra.Group.Defs 2 import Mathlib.Order.Defs.LinearOrder 3 import Mathlib.Data.Multiset.Basic 4 import Mathlib.Data.Set.Finite.Basic 5 import Mathlib.Data.Multiset.AddSub 6 import Mathlib.Data.Multiset.Bind 7 import Mathlib.Data.Fin.Tuple.Basic 8 import Mathlib.Data.Fintype.Basic 9 … module docstring, 13 lines 23 24 namespace Lax392996.Databases 25 26 /-- The values of a database: a linearly ordered type with a zero, an 27 addition, a subtraction and a multiplication, the arithmetic of terms. -/ 28 class ValueType (T : Type) extends Zero T, AddCommSemigroup T, Sub T, Mul T, LinearOrder T 29 30 variable {T : Type} [ValueType T] {n m : ℕ} 31 32 /-- A tuple of arity `n` over `T`. -/ 33 def Tuple (T : Type) (n: ℕ) := Fin n → T 34 35 instance instDecidableEqTuple [DecidableEq T] : DecidableEq (Tuple T n) := by 36 show DecidableEq (Fin n → T) 37 infer_instance 38 39 /-- The lexicographic strict order on tuples. -/ 40 instance instLTTuple : LT (Tuple T n) := 41 ⟨λ a b ↦ ∃ i : Fin n, (∀ j, j < i → a j = b j) ∧ a i < b i⟩ 42 43 instance instLETuple : LE (Tuple T n) := ⟨λ a b ↦ a < b ∨ a = b⟩ 44 45 instance instDecidableRelTupleLt : DecidableRel (λ (t₁ t₂: Tuple T n) => t₁ < t₂) := 46 λ f g ↦ 47 let _ : DecidablePred (fun i : Fin n => (∀ j, j < i → f j = g j) ∧ f i < g i) := 48 fun i => @instDecidableAnd _ _ 49 (@Fintype.decidableForallFintype (Fin n) (fun j => j < i → f j = g j) 50 (fun _j => inferInstance) _) 51 inferInstance 52 if h : ∃ i : Fin n, (∀ j, j < i → f j = g j) ∧ f i < g i then 53 isTrue (h) 54 else 55 isFalse (h) 56 57 /-- Tuples are linearly ordered, lexicographically. -/ 58 instance instLinearOrderTuple : LinearOrder (Tuple T n) where 59 le_refl := by simp[(· ≤ ·)] 60 61 le_antisymm := by 62 simp[(· ≤ ·)] 63 intro a b hab hba 64 cases hab with 65 | inl hab' => 66 cases hba with 67 | inl hba' => 68 simp only[(· < ·)] at * 69 rcases hab' with ⟨iab,hiab⟩ 70 rcases hba' with ⟨iba,hiba⟩ 71 by_cases h : iab=iba 72 . rw[h] at hiab 73 have := lt_trans hiab.right hiba.right 74 have := lt_asymm (lt_trans hiab.right hiba.right) 75 contradiction 76 . by_cases h' : iab<iba 77 . have heq := hiba.left iab h' 78 have := hiab.right 79 rw[heq] at this 80 have := lt_asymm this 81 contradiction 82 . have h'' : iba<iab := by 83 refine lt_iff_le_and_ne.mpr ?_ 84 constructor 85 . exact le_of_not_gt h' 86 . exact fun a ↦ h (id (Eq.symm a)) 87 have heq := hiab.left iba h'' 88 have := hiba.right 89 rw[heq] at this 90 have := lt_asymm this 91 contradiction 92 | inr hba' => exact Eq.symm hba' 93 | inr hab' => exact hab' 94 95 le_trans := by 96 intro a b c 97 simp only[(· ≤ ·),(· < ·)] 98 intro hab hbc 99 cases hab with 100 | inl habl => 101 cases hbc with 102 | inl hbcl => 103 apply Or.inl 104 rcases habl with ⟨iab,hiab⟩ 105 rcases hbcl with ⟨ibc,hibc⟩ 106 let i := min iab ibc 107 use i 108 have h : ∀ (j : Fin n), j < i → a j = c j := by 109 intro j hj 110 have hx := hiab.left j (lt_min_iff.mp hj).left 111 have hy := hibc.left j (lt_min_iff.mp hj).right 112 rw[hy] at hx; exact hx 113 use h 114 by_cases heq : iab = i 115 . by_cases heq' : ibc = i 116 . rw[heq] at hiab 117 rw[heq'] at hibc 118 exact lt_trans hiab.right hibc.right 119 . have h' : i < ibc := lt_of_le_of_ne (min_le_right iab ibc) (ne_comm.mpr heq') 120 have hab := hiab.right 121 rw[heq] at hab 122 have hbc := hibc.left i h' 123 rw[hbc] at hab 124 exact hab 125 . have heq'' : ibc = i := by 126 have choice : iab = i ∨ ibc = i := by 127 rcases min_choice iab ibc with hc | hc 128 . exact Or.inl hc.symm 129 . exact Or.inr hc.symm 130 tauto 131 have h' : i < iab := lt_of_le_of_ne (min_le_left iab ibc) (ne_comm.mpr heq) 132 have hbc := hibc.right 133 rw[heq''] at hbc 134 have hab := hiab.left i h' 135 rw[hab] 136 exact hbc 137 | inr hbcr => 138 rw[← hbcr] 139 exact Or.inl habl 140 | inr habr => 141 rw[habr] 142 exact hbc 143 144 le_total := by 145 intro a b 146 simp only[(· ≤ ·)] 147 by_cases heq: a=b 148 . tauto 149 . by_cases h: ∃ i, (∀ j < i, a j = b j) ∧ a i < b i 150 . apply Or.inl; apply Or.inl 151 simp only[(· < ·)] 152 tauto 153 . apply Or.inr; apply Or.inl 154 simp only[(· < ·)] 155 have hexists : ∃ k, ¬ a k = b k := by 156 refine Classical.byContradiction fun hne => ?_ 157 simp at hne 158 exact heq (funext hne) 159 have hdec : DecidablePred (fun j : Fin n => ¬ a j = b j) := fun j => instDecidableNot 160 obtain ⟨k, hk⟩ : ∃ k, k = Fin.find (λ j ↦ ¬ a j = b j) hexists := ⟨_, rfl⟩ 161 use k 162 have hspec : ¬ a k = b k := by rw [hk]; exact Fin.find_spec hexists 163 have hmin_ab : ∀ j < k, a j = b j := by 164 intro j hj 165 rw [hk] at hj 166 have := Fin.find_min hexists hj 167 simp at this 168 exact this 169 have hmin_ba : ∀ j < k, b j = a j := fun j hj => (hmin_ab j hj).symm 170 refine ⟨hmin_ba, ?_⟩ 171 simp at h 172 have hle : b k ≤ a k := h k hmin_ab 173 exact lt_iff_le_and_ne.mpr ⟨hle, fun h => hspec h.symm⟩ 174 175 lt_iff_le_not_ge := by 176 intro a b 177 simp only[(· ≤ ·)] 178 apply Iff.intro 179 . intro hab 180 constructor 181 . tauto 182 . simp only[(· < ·)] at * 183 rcases hab with ⟨i, hi⟩ 184 simp 185 constructor 186 . intro k h 187 cases hki : compare k i with 188 | eq => 189 simp at hki 190 rw[hki] 191 exact le_of_lt hi.right 192 | lt => 193 simp[compare] at hki 194 have := hi.left k hki 195 simp[this] 196 | gt => 197 simp only[compare,compareOfLessAndEq] at hki 198 by_cases hki' : k < i 199 . simp[hki'] at hki 200 . by_cases hki'' : k = i 201 . rw[hki''] at hki 202 simp at hki 203 . simp[hki'] at hki 204 have hgt : k>i := by 205 have hle := le_of_not_gt hki' 206 apply lt_of_le_of_ne 207 . exact hle 208 . exact fun a ↦ hki'' (id (Eq.symm a)) 209 have h' := h i hgt 210 rw[h'] at hi 211 have hc : a i < a i := hi.right 212 simp at hc 213 . intro heq 214 rw[heq] at hi 215 simp at hi 216 . intro ⟨h₁,h₂⟩ 217 simp at h₂ 218 have hne : a ≠ b := by 219 rw[ne_comm]; exact h₂.right 220 simp[hne] at h₁ 221 exact h₁ 222 223 toDecidableLE := 224 λ a b ↦ 225 match (inferInstance : Decidable (a<b)), (inferInstance : Decidable (a=b)) with 226 | isTrue h₁, _ => isTrue (Or.inl h₁) 227 | _, isTrue h₂ => isTrue (Or.inr h₂) 228 | isFalse h₁, isFalse h₂ => isFalse ( 229 fun h ↦ 230 match h with 231 | Or.inl h' => h₁ h' 232 | Or.inr h' => h₂ h' 233 ) 234 235 /-- A relation of arity `arity` over `T`: a finite multiset of tuples. -/ 236 def Relation (T) (arity: ℕ) := Multiset (Tuple T arity) 237 238 /-- Transport of a relation along an equality of arities. -/ 239 def Relation.cast (heq: n=m) (r: Relation T n): Relation T m := 240 Eq.ndrec (motive := fun m => Relation T m) r heq 241 242 instance instAddRelation {arity : ℕ} : Add (Relation T arity) := by 243 show Add (Multiset (Tuple T arity)) 244 infer_instance 245 246 /-- The cross product of two relations, concatenating the tuples. -/ 247 instance instHMulRelationHAddNat {a₁ a₂ : ℕ} : 248 HMul (Relation T a₁) (Relation T a₂) (Relation T (a₁+a₂)) where 249 hMul r s := 250 Multiset.map (λ ((x,y) : (Tuple T a₁)×(Tuple T a₂)) ↦ 251 Fin.append x y 252 ) (Multiset.product r s) 253 254 /-- A database: a list of named relations, each with its arity. -/ 255 def Database (T) := List (String × Σ n, Relation T n) 256 257 /-- The relation named `s` of arity `n` in a database, if any. -/ 258 def Database.find (n: ℕ) (s: String) (d: Database T) : Option (Relation T n) := 259 let rec f 260 | [] => none 261 | (s',rn)::tl => if h: n = rn.fst ∧ s=s' then some (Eq.mp (by rw[h.left]) rn.snd) else f tl 262 f d 263 264 end Lax392996.Databases 265 -
The relational algebra with multiset semantics, as syntax
The syntax of the queries. Terms over a tuple of arity are constants, attributes for , and sums, differences and products of terms; selection conditions are Boolean combinations of comparisons between terms. The queries of arity are generated by the grammar of the paper: relation names , projections on a tuple of terms, selections , cross products , multiset sums , duplicate elimination and multiset difference ; the join and the set union are syntactic sugar. The type carries two further operators, the provenance aggregation that the rewriting of duplicate elimination and difference emits, and a fused operator; a source query is one written without them.
1 import Mathlib.Logic.Basic 2 import Mathlib.Data.Nat.Init 3 import Mathlib.Order.Defs.LinearOrder 4 import Mathlib.Data.Fin.VecNotation 5 import Mathlib.Data.Multiset.Basic 6 import Lax392996.Databases 7 … module docstring, 19 lines 27 28 namespace Lax392996.RelationalAlgebra 29 30 open Lax392996.Databases 31 32 universe u v 33 34 variable {T : Type} [ValueType T] 35 36 /-- Comparison operator, as used by the `HAVING` operator. -/ 37 inductive CompOp where 38 | eq | ne | lt | le | gt | ge 39 deriving DecidableEq, Repr 40 41 /-- Semantics of a comparison operator over any linearly ordered value 42 domain. -/ 43 def CompOp.eval {V : Type u} [LinearOrder V] : CompOp → V → V → Prop 44 | .eq, a, b => a = b 45 | .ne, a, b => a ≠ b 46 | .lt, a, b => a < b 47 | .le, a, b => a ≤ b 48 | .gt, a, b => a > b 49 | .ge, a, b => a ≥ b 50 51 instance instDecidableEval {V : Type u} [LinearOrder V] (op : CompOp) (a b : V) : 52 Decidable (op.eval a b) := by 53 cases op <;> simp only [CompOp.eval] <;> infer_instance 54 55 /-- A term over a tuple of arity `n`: a constant, an attribute, or an 56 arithmetic combination. -/ 57 inductive Term (T : Sort u) (n : ℕ) where 58 | const : T → Term T n 59 | index : Fin n → Term T n 60 | add : Term T n → Term T n → Term T n 61 | sub : Term T n → Term T n → Term T n 62 | mul : Term T n → Term T n → Term T n 63 64 /-- A term read on the composite tuple: constants become data values, 65 attributes keep their index, the annotation column being the last one. -/ 66 def Term.castToAnnotatedTuple {n : ℕ} {K : Type v} (t: Term T n) : Term (T⊕K) (n+1) := match t with 67 | Term.const c => Term.const (Sum.inl c) 68 | Term.index k => Term.index (k.castLT (k.val_lt_of_le (Nat.le_add_right n 1))) 69 | Term.add t₁ t₂ => Term.add t₁.castToAnnotatedTuple t₂.castToAnnotatedTuple 70 | Term.sub t₁ t₂ => Term.sub t₁.castToAnnotatedTuple t₂.castToAnnotatedTuple 71 | Term.mul t₁ t₂ => Term.mul t₁.castToAnnotatedTuple t₂.castToAnnotatedTuple 72 73 /-- The value of a term on a tuple. -/ 74 def Term.eval {n : ℕ} (term: Term T n) (tuple: Tuple T n) := match term with 75 | Term.const a => a 76 | Term.index k => tuple k 77 | Term.add t₁ t₂ => (t₁.eval tuple) + (t₂.eval tuple) 78 | Term.sub t₁ t₂ => (t₁.eval tuple) - (t₂.eval tuple) 79 | Term.mul t₁ t₂ => (t₁.eval tuple) * (t₂.eval tuple) 80 81 /-- A comparison between two terms. -/ 82 inductive BoolTerm (T : Sort u) (n: ℕ) where 83 | EQ : Term T n → Term T n → BoolTerm T n 84 | NE : Term T n → Term T n → BoolTerm T n 85 | LE : Term T n → Term T n → BoolTerm T n 86 | LT : Term T n → Term T n → BoolTerm T n 87 | GE : Term T n → Term T n → BoolTerm T n 88 | GT : Term T n → Term T n → BoolTerm T n 89 90 /-- A comparison read on the composite tuple. -/ 91 def BoolTerm.castToAnnotatedTuple {n : ℕ} {K : Type v} (bt: BoolTerm T n): BoolTerm (T⊕K) (n+1) := 92 match bt with 93 | BoolTerm.EQ a b => BoolTerm.EQ a.castToAnnotatedTuple b.castToAnnotatedTuple 94 | BoolTerm.NE a b => BoolTerm.NE a.castToAnnotatedTuple b.castToAnnotatedTuple 95 | BoolTerm.LE a b => BoolTerm.LE a.castToAnnotatedTuple b.castToAnnotatedTuple 96 | BoolTerm.LT a b => BoolTerm.LT a.castToAnnotatedTuple b.castToAnnotatedTuple 97 | BoolTerm.GE a b => BoolTerm.GE a.castToAnnotatedTuple b.castToAnnotatedTuple 98 | BoolTerm.GT a b => BoolTerm.GT a.castToAnnotatedTuple b.castToAnnotatedTuple 99 100 /-- The truth of a comparison on a tuple. -/ 101 def BoolTerm.eval {n : ℕ} (φ: BoolTerm T n) (tuple: Tuple T n) := match φ with 102 | BoolTerm.EQ t₁ t₂ => (t₁.eval tuple) = (t₂.eval tuple) 103 | BoolTerm.NE t₁ t₂ => (t₁.eval tuple) ≠ (t₂.eval tuple) 104 | BoolTerm.LE t₁ t₂ => (t₁.eval tuple) ≤ (t₂.eval tuple) 105 | BoolTerm.LT t₁ t₂ => (t₁.eval tuple) < (t₂.eval tuple) 106 | BoolTerm.GE t₁ t₂ => (t₁.eval tuple) ≥ (t₂.eval tuple) 107 | BoolTerm.GT t₁ t₂ => (t₁.eval tuple) > (t₂.eval tuple) 108 109 @[reducible] def BoolTerm.evalDecidable {n : ℕ} (φ: BoolTerm T n) : DecidablePred φ.eval := 110 λ t => by 111 cases φ with 112 | EQ x y => simp [BoolTerm.eval]; exact (inferInstance : Decidable (x.eval t = y.eval t)) 113 | NE x y => simp [BoolTerm.eval]; exact (inferInstance : Decidable (x.eval t ≠ y.eval t)) 114 | LE x y => simp [BoolTerm.eval]; exact (inferInstance : Decidable (x.eval t ≤ y.eval t)) 115 | LT x y => simp [BoolTerm.eval]; exact (inferInstance : Decidable (x.eval t < y.eval t)) 116 | GE x y => simp [BoolTerm.eval]; exact (inferInstance : Decidable (y.eval t ≤ x.eval t)) 117 | GT x y => simp [BoolTerm.eval]; exact (inferInstance : Decidable (y.eval t < x.eval t)) 118 119 /-- A selection condition: a Boolean combination of comparisons. -/ 120 inductive Selection (T : Sort u) (n: ℕ) where 121 | BT : BoolTerm T n → Selection T n 122 | Not : Selection T n → Selection T n 123 | And : Selection T n → Selection T n → Selection T n 124 | Or : Selection T n → Selection T n → Selection T n 125 | True : Selection T n 126 127 /-- A selection condition read on the composite tuple. -/ 128 def Selection.castToAnnotatedTuple {n : ℕ} {K : Type v} (f: Selection T n): Selection (T⊕K) (n+1) := match f with 129 | Selection.BT t => Selection.BT t.castToAnnotatedTuple 130 | Selection.Not φ => Selection.Not φ.castToAnnotatedTuple 131 | Selection.And φ₁ φ₂ => Selection.And φ₁.castToAnnotatedTuple φ₂.castToAnnotatedTuple 132 | Selection.Or φ₁ φ₂ => Selection.Or φ₁.castToAnnotatedTuple φ₂.castToAnnotatedTuple 133 | Selection.True => Selection.True 134 135 /-- The truth of a selection condition on a tuple. -/ 136 def Selection.eval {n : ℕ} (φ: Selection T n) (tuple: Tuple T n) := match φ with 137 | Selection.BT φ => φ.eval tuple 138 | Selection.Not φ => ¬ (φ.eval tuple) 139 | Selection.And φ₁ φ₂ => (φ₁.eval tuple) ∧ (φ₂.eval tuple) 140 | Selection.Or φ₁ φ₂ => (φ₁.eval tuple) ∨ (φ₂.eval tuple) 141 | Selection.True => true 142 143 @[reducible] def Selection.evalDecidable {n : ℕ} (φ : Selection T n) : DecidablePred φ.eval := 144 λ t => match φ with 145 | Selection.BT φ => φ.evalDecidable t 146 | Selection.Not φ => match φ.evalDecidable t with 147 | isTrue h => isFalse (by simp [Selection.eval, h]) 148 | isFalse h => isTrue (by simp [Selection.eval, h]) 149 | Selection.And φ₁ φ₂ => match φ₁.evalDecidable t, φ₂.evalDecidable t with 150 | isTrue h₁, isTrue h₂ => isTrue (by simp [Selection.eval, h₁, h₂]) 151 | isFalse h, _ | _, isFalse h => isFalse (by simp [Selection.eval, h]) 152 | Selection.Or φ₁ φ₂ => match φ₁.evalDecidable t, φ₂.evalDecidable t with 153 | isTrue h, _ | _, isTrue h => isTrue (by simp [Selection.eval, h]) 154 | isFalse h₁, isFalse h₂ => isFalse (by simp [Selection.eval, h₁, h₂]) 155 | Selection.True => isTrue (rfl) 156 157 /-- An aggregate function on sequences of values, the aggregate interface 158 of the fused `HAVING` operator. -/ 159 def SeqAggFunc (T : Type) := List T → T 160 161 /-- The queries, indexed by arity: the operators of the paper's grammar, 162 the provenance aggregation `ProvSum` that the rewriting emits, and the 163 fused `HAVING` operator. -/ 164 inductive Query (T: Type) : ℕ → Type 165 | Rel : (n: ℕ) → String → Query T n 166 | Proj {n m : ℕ} : Tuple (Term T n) m → Query T n → Query T m 167 | Sel {n : ℕ} : Selection T n → Query T n → Query T n 168 | Prod {n₁ n₂ n : ℕ} {hn: n₁+n₂=n} : Query T n₁ → Query T n₂ → Query T n 169 | Sum {n : ℕ} : Query T n → Query T n → Query T n 170 | Dedup {n : ℕ} : Query T n → Query T n 171 | Diff {n : ℕ} : Query T n → Query T n → Query T n 172 /-- Provenance aggregation: group by the key columns of the first 173 argument and `⊕`-sum the term of the second over each group into a single 174 trailing output column. It is the target of the rewriting of duplicate 175 elimination and of difference. -/ 176 | ProvSum {m n₁ : ℕ} : Tuple (Fin m) n₁ → Term T m → Query T m → Query T (n₁+1) 177 /-- The fused `HAVING` operator: grouping by the indices of the first 178 argument, computing the sequence aggregates of the third argument applied 179 to the terms of the second, each group read in the canonical tuple order, 180 and keeping only the groups whose aggregate value in column `l` compares, 181 through the comparison operator, with the value of the term on the group 182 key. The output has the group key followed by the aggregate values. -/ 183 | Having {m n₁ n₂ : ℕ} : Tuple (Fin m) n₁ → Tuple (Term T m) n₂ → Tuple (SeqAggFunc T) n₂ → 184 CompOp → Fin n₂ → Term T n₁ → Query T m → Query T (n₁+n₂) 185 186 /-- The source fragment: the queries written with the operators of the 187 paper's grammar only, without `ProvSum` and `Having`. -/ 188 def Query.source {n : ℕ} (q: Query T n): Prop := match q with 189 | Query.Rel n s => True 190 | Query.Proj _ q => q.source 191 | Query.Sel _ q => q.source 192 | Query.Prod q₁ q₂ => q₁.source ∧ q₂.source 193 | Query.Sum q₁ q₂ => q₁.source ∧ q₂.source 194 | Query.Dedup q => q.source 195 | Query.Diff q₁ q₂ => q₁.source ∧ q₂.source 196 | Query.ProvSum _ _ q => False 197 | Query.Having _ _ _ _ _ _ _ => False 198 199 /-- The arguments of a source cross product are source queries. A proof 200 carried as a definition, since the concept dialect has no theorem command; 201 the recursive definitions over source queries use it. -/ 202 def Query.source_prod {n n₂ : ℕ} {q: Query T n} : 203 q.source → ∀ {n₁} {q₁: Query T n₁} {q₂: Query T n₂} {hn: n₁+n₂=n} 204 (_: q = @Query.Prod T n₁ n₂ n hn q₁ q₂), q₁.source ∧ q₂.source := by 205 intro hna n₁ q₁ q₂ hn₁ hq 206 unfold Query.source at hna 207 simp[hq] at hna 208 assumption 209 210 /-- The arguments of a source multiset sum are source queries. -/ 211 def Query.source_sum {n : ℕ} {q: Query T n} : 212 q.source → ∀ {q₁: Query T n} {q₂: Query T n} (_: q = Query.Sum q₁ q₂), q₁.source ∧ q₂.source := by 213 intro hna q₁ q₂ hq 214 unfold Query.source at hna 215 simp[hq] at hna 216 assumption 217 218 /-- The arguments of a source difference are source queries. -/ 219 def Query.source_diff {n : ℕ} {q: Query T n} : 220 q.source → ∀ {q₁: Query T n} {q₂: Query T n} (_: q = Query.Diff q₁ q₂), q₁.source ∧ q₂.source := by 221 intro hna q₁ q₂ hq 222 unfold Query.source at hna 223 simp[hq] at hna 224 assumption 225 226 /-- The argument of a source projection is a source query. -/ 227 def Query.source_proj {n : ℕ} {q: Query T n} : 228 q.source → ∀ {m} {t} {q': Query T m} (_: q = Query.Proj t q'), q'.source := by 229 intro hna m t q' hq 230 unfold Query.source at hna 231 rw[hq] at hna 232 assumption 233 234 /-- The argument of a source selection is a source query. -/ 235 def Query.source_sel {n : ℕ} {q: Query T n} : 236 q.source → ∀ {φ} {q': Query T n} (_: q = Query.Sel φ q'), q'.source := by 237 intro hna φ q' hq 238 unfold Query.source at hna 239 rw[hq] at hna 240 assumption 241 242 /-- The argument of a source duplicate elimination is a source query. -/ 243 def Query.source_dedup {n : ℕ} {q: Query T n} : 244 q.source → ∀ {q': Query T n} (_: q = Query.Dedup q'), q'.source := by 245 intro hna q' hq 246 unfold Query.source at hna 247 rw[hq] at hna 248 assumption 249 250 /-- The arity of a query. -/ 251 def Query.arity {n : ℕ} (_: Query T n) := n 252 253 /-- The measure the recursive semantics is defined along: the depth of the 254 query, aggregation operators counting for three. -/ 255 def Query.aggdepth2_plus_depth {n : ℕ} (q: Query T n) : ℕ := match q with 256 | Query.Rel n s => 0 257 | Query.Proj _ q => let d := q.aggdepth2_plus_depth; d+1 258 | Query.Sel _ q => let d := q.aggdepth2_plus_depth; d+1 259 | Query.Prod q₁ q₂ => 260 let d₁ := q₁.aggdepth2_plus_depth 261 let d₂ := q₂.aggdepth2_plus_depth 262 (max d₁ d₂)+1 263 | Query.Sum q₁ q₂ => 264 let d₁ := q₁.aggdepth2_plus_depth 265 let d₂ := q₂.aggdepth2_plus_depth 266 (max d₁ d₂)+1 267 | Query.Dedup q => let d := q.aggdepth2_plus_depth; d+1 268 | Query.Diff q₁ q₂ => 269 let d₁ := q₁.aggdepth2_plus_depth 270 let d₂ := q₂.aggdepth2_plus_depth 271 (max d₁ d₂)+1 272 | Query.ProvSum _ _ q => let d := q.aggdepth2_plus_depth; (d+3) 273 | Query.Having _ _ _ _ _ _ q => let d := q.aggdepth2_plus_depth; (d+3) 274 275 end Lax392996.RelationalAlgebra 276 -
Multiset semantics of the relational algebra
The semantics of a query on a database , clause by clause: ; ; ; ; ; keeps one copy of each tuple of ; and removes from every copy of a tuple occurring in . The definition also interprets the two extra operators: the provenance aggregation sums its term over each group of the key columns, and the fused operator computes its aggregates over each group read in the canonical tuple order. The seven claims are the clauses of the paper.
- def✓
Lax392996.MultisetSemantics(1st statement) - def✓
Lax392996.MultisetSemantics(2nd statement) - def✓
Lax392996.MultisetSemantics(3rd statement) - def✓
Lax392996.MultisetSemantics(4th statement) - def✓
Lax392996.MultisetSemantics(5th statement) - def✓
Lax392996.MultisetSemantics(6th statement) - def✓
Lax392996.MultisetSemantics(7th statement)
1 import Mathlib.Data.Multiset.Dedup 2 import Mathlib.Data.Multiset.Filter 3 import Mathlib.Data.Multiset.Sort 4 import Mathlib.Data.Multiset.Basic 5 import Mathlib.Data.Multiset.MapFold 6 import Mathlib.Data.Fin.VecNotation 7 import Lax392996.Databases 8 import Lax392996.RelationalAlgebra 9 … module docstring, 19 lines 29 30 namespace Lax392996.MultisetSemantics 31 32 open Lax392996.Databases Lax392996.RelationalAlgebra 33 34 variable {T : Type} [ValueType T] 35 36 /-- Addition as a binary function, the fold of the `⊕`-sum performed by 37 the provenance aggregation `Query.ProvSum`. -/ 38 def addFn (a b : T) := a + b 39 40 instance instCommutativeAddFn : @Std.Commutative T addFn where 41 comm := add_comm 42 43 instance instAssociativeAddFn : @Std.Associative T addFn where 44 assoc := add_assoc 45 46 /-- The occurrences of the group of key `g` in relation `r`: the multiset of 47 matching tuples, as a list sorted by the canonical linear order on tuples. 48 The sort order plays the role of the ordering along which 49 non-commutative sequence aggregates read the occurrences of a group; for 50 commutative aggregates it is irrelevant. -/ 51 def Relation.groupSeq {m n₁ : ℕ} (is : Tuple (Fin m) n₁) (r : Relation T m) (g : Tuple T n₁) : 52 List (Tuple T m) := 53 Multiset.sort 54 (@Multiset.filter _ (fun u => ∀ k' : Fin n₁, u (is k') = g k') 55 (fun u => @Nat.decidableForallFin n₁ (fun k' => u (is k') = g k') (fun _ => inferInstance)) r) 56 (· ≤ ·) 57 58 /-- Multiset semantics of a query over a plain database. 59 60 The `Diff` case is all-or-nothing difference: every copy of a tuple that 61 occurs at all in `r₂` is removed from `r₁`, which is what the monus-based 62 annotated semantics of difference gives on `0`/`1`-annotated inputs. -/ 63 def Query.evaluate {n : ℕ} (q: Query T n) (d: Database T): Relation T n := match q with 64 | Query.Rel n s => 65 match d.find n s with 66 | none => (∅: Multiset (Tuple T n)) 67 | some rn => rn 68 | Query.Proj ts q => let r := evaluate q d; Multiset.map (λ t ↦ λ k ↦ (ts k).eval t) r 69 | Query.Sel φ q => let r := evaluate q d; @Multiset.filter _ φ.eval φ.evalDecidable r 70 | @Query.Prod _ n₁ n₂ n hn q₁ q₂ => 71 let r₁ := evaluate q₁ d 72 let r₂ := evaluate q₂ d 73 (r₁ * r₂).cast hn 74 | Query.Sum q₁ q₂ => let r₁ := evaluate q₁ d; let r₂ := evaluate q₂ d; r₁ + r₂ 75 | Query.Dedup q => let r := evaluate q d; Multiset.dedup r 76 | Query.Diff q₁ q₂ => 77 let r₁ := evaluate q₁ d 78 let r₂ : Multiset (Tuple T _) := evaluate q₂ d 79 r₁.filter (fun t ↦ t ∉ r₂) 80 | @Query.ProvSum _ m n₁ is t q => 81 let r := evaluate (Query.Dedup (Query.Proj (λ (k: Fin n₁) ↦ Term.index (is k)) q)) d 82 let s := evaluate q d 83 r.map (λ g ↦ Fin.append g ( 84 λ _: Fin 1 ↦ ( 85 (@Multiset.filter _ (λ u ↦ ∀ k': Fin n₁, u (is k') = g k') 86 (fun u => @Nat.decidableForallFin n₁ (fun k' => u (is k') = g k') (fun _ => inferInstance)) 87 s).map (λ u ↦ t.eval u) 88 ).fold addFn 0 89 )) 90 | @Query.Having _ m n₁ n₂ is ts fs op l s q => 91 let keys := evaluate (Query.Dedup (Query.Proj (λ (k: Fin n₁) ↦ Term.index (is k)) q)) d 92 let r := evaluate q d 93 Multiset.map 94 (λ g ↦ Fin.append g 95 (λ (k: Fin n₂) ↦ (fs k) ((Relation.groupSeq is r g).map (ts k).eval))) 96 (@Multiset.filter _ 97 (λ g ↦ op.eval ((fs l) ((Relation.groupSeq is r g).map (ts l).eval)) (s.eval g)) 98 (fun g => instDecidableEval op _ _) 99 keys) 100 termination_by q.aggdepth2_plus_depth 101 decreasing_by 102 all_goals simp[Query.aggdepth2_plus_depth] 103 any_goals refine Nat.lt_add_one_of_le ?_ 104 any_goals exact Nat.le_max_left _ _ 105 any_goals exact Nat.le_max_right _ _ 106 107 /-- **relation**: `⟦R⟧_I ≝ I(R)`. -/ 108 axiom eval_rel : ∀ {n : ℕ} (R : String) (d : Database T), 109 Query.evaluate (Query.Rel n R) d = (d.find n R).getD (∅ : Multiset (Tuple T n)) 110 111 /-- **projection**: `⟦Π_{t₁,…,t_n}(q)⟧_I ≝ {|(t₁(u),…,t_n(u)) | u ∈ ⟦q⟧_I|}`. -/ 112 axiom eval_proj : ∀ {n k : ℕ} (ts : Tuple (Term T k) n) (q : Query T k) (d : Database T), 113 Query.evaluate (Query.Proj ts q) d = (Query.evaluate q d).map (fun u l => (ts l).eval u) 114 115 /-- **selection**: `⟦σ_φ(q)⟧_I ≝ {|u | u ∈ ⟦q⟧_I, φ(u)|}`. -/ 116 axiom eval_sel : ∀ {n : ℕ} (φ : Selection T n) (q : Query T n) (d : Database T), 117 Query.evaluate (Query.Sel φ q) d = @Multiset.filter _ φ.eval φ.evalDecidable (Query.evaluate q d) 118 119 /-- **cross product**: `⟦q₁ × q₂⟧_I ≝ ⟦q₁⟧_I × ⟦q₂⟧_I`. -/ 120 axiom eval_prod : ∀ {n k₁ k₂ : ℕ} {hn : k₁ + k₂ = n} (q₁ : Query T k₁) (q₂ : Query T k₂) (d : Database T), 121 Query.evaluate (Query.Prod (hn := hn) q₁ q₂) d = ((Query.evaluate q₁ d) * (Query.evaluate q₂ d)).cast hn 122 123 /-- **multiset sum**: `⟦q₁ ⊎ q₂⟧_I ≝ ⟦q₁⟧_I ⊎ ⟦q₂⟧_I`. -/ 124 axiom eval_sum : ∀ {n : ℕ} (q₁ q₂ : Query T n) (d : Database T), 125 Query.evaluate (Query.Sum q₁ q₂) d = Query.evaluate q₁ d + Query.evaluate q₂ d 126 127 /-- **duplicate elimination**: `⟦ε(q)⟧_I` maps `t` to `1` when `⟦q⟧_I(t) > 0` 128 and to `0` otherwise. -/ 129 axiom eval_dedup : ∀ {n : ℕ} (q : Query T n) (d : Database T), 130 Query.evaluate (Query.Dedup q) d = (Query.evaluate q d).dedup 131 132 /-- **multiset difference**: every copy of a tuple occurring at all in `⟦q₂⟧_I` 133 is removed from `⟦q₁⟧_I`. -/ 134 axiom eval_diff : ∀ {n : ℕ} (q₁ q₂ : Query T n) (d : Database T) (r₂ : Multiset (Tuple T n)), 135 r₂ = Query.evaluate q₂ d → 136 Query.evaluate (Query.Diff q₁ q₂) d = (Query.evaluate q₁ d).filter (fun u => u ∉ r₂) 137 138 end Lax392996.MultisetSemantics 139 - def✓
-
The Personnel example
The running example of the paper: the relation of arity 4 with seven tuples, giving an id, a name, a position and a city (1, Juma, Director, Nairobi; 2, Paul, Janitor, Nairobi; 3, David, Analyst, Paris; 4, Ellen, Field agent, Beijing; 5, Aaheli, Double agent, Paris; 6, Nancy, HR, Paris; 7, Jing, Analyst, Beijing), the database holding it, and the query asking for the cities where at least two persons work, , the join being a selection over a cross product. Values are strings, ordered as strings; the claim is Example 2, .
1 import Mathlib.Data.Fin.VecNotation 2 import Mathlib.Data.String.Basic 3 import Mathlib.Data.Multiset.Basic 4 import Lax392996.Databases 5 import Lax392996.RelationalAlgebra 6 import Lax392996.MultisetSemantics 7 … module docstring, 17 lines 25 26 namespace Lax392996.PersonnelExample 27 28 open Lax392996.Databases Lax392996.RelationalAlgebra Lax392996.MultisetSemantics 29 30 /-- Strings as values, ordered as strings; the arithmetic of terms, which 31 the example does not use, is trivial on them. -/ 32 instance instValueTypeString : ValueType String where 33 zero := "" 34 add _ _ := "" 35 sub _ _ := "" 36 mul _ _ := "" 37 add_comm _ _ := rfl 38 add_assoc _ _ _ := rfl 39 40 /-- The relation `Personnel` of the paper's Table 1: id, name, position, city. -/ 41 def personnel : Relation String 4 := Multiset.ofList [ 42 !["1", "Juma", "Director", "Nairobi"], 43 !["2", "Paul", "Janitor", "Nairobi"], 44 !["3", "David", "Analyst", "Paris"], 45 !["4", "Ellen", "Field agent", "Beijing"], 46 !["5", "Aaheli", "Double agent", "Paris"], 47 !["6", "Nancy", "HR", "Paris"], 48 !["7", "Jing", "Analyst", "Beijing"]] 49 50 /-- The database `I`, with its one relation. -/ 51 def instanceI : Database String := [("Personnel", ⟨4, personnel⟩)] 52 53 /-- The query `q_city`: the cities where at least two persons work, as 54 duplicate elimination of a projection of a selection over the cross 55 product of `Personnel` with itself. Attributes are numbered from 0 here, 56 from 1 in the paper. -/ 57 def qcity : Query String 1 := 58 Query.Dedup (Query.Proj ![Term.index 3] 59 (Query.Sel (Selection.And (Selection.BT (BoolTerm.EQ (Term.index 3) (Term.index 7))) 60 (Selection.BT (BoolTerm.LT (Term.index 0) (Term.index 4)))) 61 (@Query.Prod _ 4 4 8 rfl (Query.Rel 4 "Personnel") (Query.Rel 4 "Personnel")))) 62 63 /-- Example 2: the answer of `q_city` on `I`. -/ 64 axiom qcity_answer : 65 Query.evaluate qcity instanceI = Multiset.ofList [!["Nairobi"], !["Paris"], !["Beijing"]] 66 67 end Lax392996.PersonnelExample 68 -
no assumptions
The library's theorem: the random world of the annotated answer is the answer on the random world, by induction on the query, and the disjunctive annotation of a tuple holds at a valuation exactly when the tuple belongs to that random world.
-
no assumptions
The library's theorem, by structural induction on the query: each rule is shown to commute with the composite reading of the annotated semantics, the difference rule through the two semijoin identities of the library.
-
The provenance-aware rewriting of queries, rules (R1) to (R4)
The rewriting of a source query of arity into a query of arity over whose last column carries the annotation, defined bottom up by the rules of the paper: (R1) a projection becomes ; (R2) a cross product becomes ; (R3) a duplicate elimination becomes , the grouping by the data columns with the -sum of the annotation column; (R4) a difference becomes the multiset sum of the tuples of whose data part survives the set difference of the data projections, annotation unchanged, and the tuples of joined with the -aggregated on the data columns, annotated by . Relation names, selections and multiset sums are rewritten homomorphically. The four claims are the rules as the equations they are.
- def✓
Lax392996.RewritingRules(1st statement) - def✓
Lax392996.RewritingRules(2nd statement) - def✓
Lax392996.RewritingRules(3rd statement) - def✓
Lax392996.RewritingRules(4th statement)
1 import Mathlib.Data.Fin.VecNotation 2 import Lax392996.Databases 3 import Lax392996.RelationalAlgebra 4 … module docstring, 21 lines 26 27 namespace Lax392996.RewritingRules 28 29 open Lax392996.Databases Lax392996.RelationalAlgebra 30 31 variable {T : Type} 32 33 /-- The rewriting of a source query, rules (R1) to (R4) applied bottom up. -/ 34 def Query.rewriting {n : ℕ} {K : Type} [ValueType T] (q: Query T n) (hq: q.source) : 35 Query (T⊕K) (n+1) := match q with 36 | Query.Rel n s => Query.Rel (n+1) s 37 | Query.Proj ts q => 38 let ts := 39 (λ (k: Fin (n+1)) => if h : ↑k<n then (ts ⟨k,h⟩).castToAnnotatedTuple 40 else Term.index (Fin.last q.arity)) 41 Query.Proj ts (rewriting q (Query.source_proj hq rfl)) 42 | Query.Sel φ q => Query.Sel φ.castToAnnotatedTuple (rewriting q (Query.source_sel hq rfl)) 43 | @Query.Prod T n₁ n₂ n hn q₁ q₂ => 44 let tmp := 45 @Query.Prod (T⊕K) (n₁+1) (n₂+1) (n+2) (by omega) (rewriting q₁ (Query.source_prod hq rfl).left) 46 let product := tmp (rewriting q₂ (Query.source_prod hq rfl).right) 47 let ts : Tuple (Term (T⊕K) (n+2)) (n+1) := 48 (λ k: Fin (n+1) => 49 if ↑k<n₁ then Term.index (k.castLE (by simp)) 50 else if (↑k<n: Prop) then Term.index (Fin.ofNat _ (↑k+1)) 51 else Term.mul (Term.index (Fin.ofNat _ n₁)) (Term.index (Fin.ofNat _ (n+1)))) 52 Query.Proj ts product 53 | Query.Sum q₁ q₂ => 54 Query.Sum (rewriting q₁ (Query.source_sum hq rfl).left) (rewriting q₂ (Query.source_sum hq rfl).right) 55 | Query.Dedup q => 56 let q' := rewriting q (Query.source_dedup hq rfl) 57 Query.ProvSum (λ (k: Fin n) ↦ k.castLE (by simp)) (Term.index (Fin.last n)) q' 58 | Query.Diff q₁ q₂ => 59 let q'₁ := rewriting q₁ (Query.source_diff hq rfl).left 60 let q'₂ := rewriting q₂ (Query.source_diff hq rfl).right 61 let joinCond₁ := 62 ((List.range n).map 63 (λ k ↦ @Selection.BT (T⊕K) (2*n+1) 64 (BoolTerm.EQ (Term.index (Fin.ofNat _ k)) (Term.index (Fin.ofNat _ (k+n+1)))))).foldr 65 (λ t t' ↦ Selection.And t t') Selection.True 66 let prod₁t := λ r ↦ Query.Sel joinCond₁ (@Query.Prod _ (n+1) n (2*n+1) (by omega) q'₁ r) 67 let prod₁r := Query.Dedup (Query.Diff 68 (Query.Proj (λ (k: Fin n) ↦ (Term.index (k.castLE (Nat.le_succ _)))) q'₁) 69 (Query.Proj (λ (k: Fin n) ↦ (Term.index (k.castLE (Nat.le_succ _)))) q'₂)) 70 let prod₁ := prod₁t (prod₁r) 71 let joinCond₂ := 72 ((List.range n).map 73 (λ k ↦ @Selection.BT (T⊕K) (2*n+2) 74 (BoolTerm.EQ (Term.index (Fin.ofNat _ k)) (Term.index (Fin.ofNat _ (k+n+1)))))).foldr 75 (λ t t' ↦ Selection.And t t') Selection.True 76 have h₂ : (2*n+2 - (n+1): ℕ) = n+1 := by omega 77 let prod₂t := λ r ↦ Query.Sel joinCond₂ (@Query.Prod _ (n+1) (n+1) (2*n+2) (by omega) q'₁ r) 78 let prod₂r := Query.ProvSum (λ (k: Fin n) ↦ (k.castLE (by simp))) (Term.index (Fin.last n)) q'₂ 79 let prod₂ := prod₂t (prod₂r) 80 let ts₁ := (λ (k: Fin (n+1)) ↦ Term.index (k.castLE (by omega))) 81 let ts₂ := (λ (k: Fin (n+1)) ↦ if ↑k<n then Term.index (k.castLE (by omega)) 82 else Term.sub (Term.index (Fin.ofNat _ n)) (Term.index (Fin.last (2*n+1)))) 83 Query.Sum (Query.Proj ts₁ prod₁) (Query.Proj ts₂ prod₂) 84 | Query.ProvSum _ _ _ => by simp[Query.source] at hq 85 | Query.Having _ _ _ _ _ _ _ => by simp[Query.source] at hq 86 87 /-- **(R1) projection.** `Π_{t₁,…,t_n}(q)` is rewritten to 88 `Π_{t₁,…,t_n,#(k+1)}(q̂)`: the terms are carried over unchanged and the 89 annotation column of the rewritten argument is appended. -/ 90 axiom rule_projection : ∀ [ValueType T] {K : Type} {n k : ℕ} (ts : Tuple (Term T k) n) (q : Query T k) 91 (hq : (Query.Proj ts q).source), 92 Query.rewriting (K := K) (Query.Proj ts q) hq 93 = Query.Proj 94 (fun l : Fin (n + 1) => 95 if h : (l : ℕ) < n then (ts ⟨l, h⟩).castToAnnotatedTuple 96 else Term.index (Fin.last q.arity)) 97 (Query.rewriting q (Query.source_proj hq rfl)) 98 99 /-- **(R2) cross product.** `q₁ × q₂` is rewritten to 100 `Π_{#1,…,#k₁,#(k₁+2),…,#(k₁+k₂+1),#(k₁+1) ⊗ #(k₁+k₂+2)}(q̂₁ × q̂₂)`: the two 101 data blocks are kept, the two annotation columns are multiplied. -/ 102 axiom rule_product : ∀ [ValueType T] {K : Type} {n n₁ n₂ : ℕ} {hn : n₁ + n₂ = n} 103 (q₁ : Query T n₁) (q₂ : Query T n₂) (hq : (Query.Prod (hn := hn) q₁ q₂).source), 104 Query.rewriting (K := K) (Query.Prod (hn := hn) q₁ q₂) hq 105 = Query.Proj 106 (fun l : Fin (n + 1) => 107 if (l : ℕ) < n₁ then Term.index (l.castLE (by simp)) 108 else if ((l : ℕ) < n : Prop) then Term.index (Fin.ofNat _ ((l : ℕ) + 1)) 109 else Term.mul (Term.index (Fin.ofNat _ n₁)) (Term.index (Fin.ofNat _ (n + 1)))) 110 (@Query.Prod (T ⊕ K) (n₁ + 1) (n₂ + 1) (n + 2) (by omega) 111 (Query.rewriting q₁ (Query.source_prod hq rfl).left) 112 (Query.rewriting q₂ (Query.source_prod hq rfl).right)) 113 114 /-- **(R3) duplicate elimination.** `ε(q)` is rewritten to 115 `γ_{1,…,k}[#(k+1) : ⊕](q̂)`: group by the data columns and `⊕`-sum the 116 annotation column. -/ 117 axiom rule_dupelim : ∀ [ValueType T] {K : Type} {n : ℕ} (q : Query T n) (hq : (Query.Dedup q).source), 118 Query.rewriting (K := K) (Query.Dedup q) hq 119 = Query.ProvSum (fun l : Fin n => l.castLE (by simp)) (Term.index (Fin.last n)) 120 (Query.rewriting q (Query.source_dedup hq rfl)) 121 122 /-- **(R4) multiset difference.** `q₁ - q₂` is rewritten to the multiset sum of 123 two branches: the tuples of `q̂₁` whose data part survives the set difference of 124 the two data projections, carrying their annotation unchanged; and the tuples of 125 `q̂₁` matched against the `⊕`-aggregated `q̂₂`, carrying `α ⊖ Σβ`. Both branches 126 are joins on the `k` data columns. -/ 127 axiom rule_difference : ∀ [ValueType T] {K : Type} {n : ℕ} (q₁ q₂ : Query T n) 128 (hq : (Query.Diff q₁ q₂).source), 129 Query.rewriting (K := K) (Query.Diff q₁ q₂) hq 130 = (let q'₁ := Query.rewriting (K := K) q₁ (Query.source_diff hq rfl).left 131 let q'₂ := Query.rewriting (K := K) q₂ (Query.source_diff hq rfl).right 132 let joinCond₁ := 133 ((List.range n).map 134 (fun j => @Selection.BT (T ⊕ K) (2 * n + 1) 135 (BoolTerm.EQ (Term.index (Fin.ofNat _ j)) (Term.index (Fin.ofNat _ (j + n + 1)))))).foldr 136 (fun t t' => Selection.And t t') Selection.True 137 let prod₁t := fun r => Query.Sel joinCond₁ (@Query.Prod _ (n + 1) n (2 * n + 1) (by omega) q'₁ r) 138 let prod₁r := 139 Query.Dedup (Query.Diff 140 (Query.Proj (fun j : Fin n => Term.index (j.castLE (Nat.le_succ _))) q'₁) 141 (Query.Proj (fun j : Fin n => Term.index (j.castLE (Nat.le_succ _))) q'₂)) 142 let prod₁ := prod₁t prod₁r 143 let joinCond₂ := 144 ((List.range n).map 145 (fun j => @Selection.BT (T ⊕ K) (2 * n + 2) 146 (BoolTerm.EQ (Term.index (Fin.ofNat _ j)) (Term.index (Fin.ofNat _ (j + n + 1)))))).foldr 147 (fun t t' => Selection.And t t') Selection.True 148 let prod₂t := fun r => Query.Sel joinCond₂ (@Query.Prod _ (n + 1) (n + 1) (2 * n + 2) (by omega) q'₁ r) 149 let prod₂r := Query.ProvSum (fun j : Fin n => j.castLE (by simp)) (Term.index (Fin.last n)) q'₂ 150 let prod₂ := prod₂t prod₂r 151 let ts₁ := fun j : Fin (n + 1) => Term.index (j.castLE (by omega)) 152 let ts₂ := fun j : Fin (n + 1) => 153 if (j : ℕ) < n then Term.index (j.castLE (by omega)) 154 else Term.sub (Term.index (Fin.ofNat _ n)) (Term.index (Fin.last (2 * n + 1))) 155 Query.Sum (Query.Proj ts₁ prod₁) (Query.Proj ts₂ prod₂)) 156 157 end Lax392996.RewritingRules 158 - def✓
-
Correctness of the provenance-aware rewriting, rules (R1) to (R4)
Let be a source query, an m-semiring with decidable equality and an alternative linear order, a -instance, and the query obtained from by applying the rewriting rules bottom up. Then : the annotated semantics of on , read as a plain relation with the annotation in the last column, is the multiset semantics of on the composite reading of . This is the theorem of the paper restricted to rules (R1) to (R4): the paper's statement also covers the aggregation rule (R5), which this submission does not state; the library proves an analogue of it, on its general syntax with symbolic aggregate tokens, outside the paper's syntax.
1 import Lax392996.SemiringsWithMonus 2 import Lax392996.Databases 3 import Lax392996.AnnotatedDatabases 4 import Lax392996.RelationalAlgebra 5 import Lax392996.MultisetSemantics 6 import Lax392996.AnnotatedSemantics 7 import Lax392996.RewritingRules 8 … module docstring, 17 lines 26 27 namespace Lax392996.RewritingCorrectness 28 29 open Lax392996.SemiringsWithMonus Lax392996.Databases Lax392996.AnnotatedDatabases 30 open Lax392996.RelationalAlgebra Lax392996.MultisetSemantics Lax392996.AnnotatedSemantics 31 open Lax392996.RewritingRules 32 33 /-- `⟪q⟫_Î = ⟦q̂⟧_Î`, for `q` in the fragment the rules (R1)–(R4) cover. -/ 34 axiom rewriting_valid : ∀ {T : Type} [ValueType T] {K : Type} {n : ℕ} 35 [SemiringWithMonus K] [DecidableEq K] [HasAltLinearOrder K] 36 (q : Query T n) (hq : q.source) (d : AnnotatedDatabase T K), 37 (Query.evaluateAnnotated q hq d).toComposite 38 = Query.evaluate (Query.rewriting q hq) d.toComposite 39 40 end Lax392996.RewritingCorrectness 41 -
Correctness of the provenance-aware rewriting, rules (R1) to (R4)
Let be a source query, an m-semiring with decidable equality and an alternative linear order, a -instance, and the query obtained from by applying the rewriting rules bottom up. Then : the annotated semantics of on , read as a plain relation with the annotation in the last column, is the multiset semantics of on the composite reading of . This is the theorem of the paper restricted to rules (R1) to (R4): the paper's statement also covers the aggregation rule (R5), which this submission does not state; the library proves an analogue of it, on its general syntax with symbolic aggregate tokens, outside the paper's syntax.
1 import Lax392996.SemiringsWithMonus 2 import Lax392996.Databases 3 import Lax392996.AnnotatedDatabases 4 import Lax392996.RelationalAlgebra 5 import Lax392996.MultisetSemantics 6 import Lax392996.AnnotatedSemantics 7 import Lax392996.RewritingRules 8 … module docstring, 17 lines 26 27 namespace Lax392996.RewritingCorrectness 28 29 open Lax392996.SemiringsWithMonus Lax392996.Databases Lax392996.AnnotatedDatabases 30 open Lax392996.RelationalAlgebra Lax392996.MultisetSemantics Lax392996.AnnotatedSemantics 31 open Lax392996.RewritingRules 32 33 /-- `⟪q⟫_Î = ⟦q̂⟧_Î`, for `q` in the fragment the rules (R1)–(R4) cover. -/ 34 axiom rewriting_valid : ∀ {T : Type} [ValueType T] {K : Type} {n : ℕ} 35 [SemiringWithMonus K] [DecidableEq K] [HasAltLinearOrder K] 36 (q : Query T n) (hq : q.source) (d : AnnotatedDatabase T K), 37 (Query.evaluateAnnotated q hq d).toComposite 38 = Query.evaluate (Query.rewriting q hq) d.toComposite 39 40 end Lax392996.RewritingCorrectness 41 -
The Personnel example, rewritten
The paper's Example 11: the rewriting rules applied bottom up to , for any annotation type , give , the cross product rewritten by (R2), the projection by (R1) and the duplicate elimination by (R3), the selection carried over to the composite tuples. The claim is that equation, on the queries as syntax; the equality of its two semantics is an instance of the correctness theorem. Attributes are numbered from 0 here, from 1 in the paper.
1 import Mathlib.Data.Fin.VecNotation 2 import Lax392996.Databases 3 import Lax392996.RelationalAlgebra 4 import Lax392996.RewritingRules 5 import Lax392996.PersonnelExample 6 … module docstring, 15 lines 22 23 namespace Lax392996.RewritingExample 24 25 open Lax392996.Databases Lax392996.RelationalAlgebra Lax392996.RewritingRules 26 open Lax392996.PersonnelExample 27 28 /-- The rewritten query, as the paper traces it. -/ 29 def qcityRewritten (K : Type) : Query (String ⊕ K) 2 := 30 Query.ProvSum (fun k : Fin 1 => k.castLE (by omega)) (Term.index 1) 31 (Query.Proj ![Term.index 3, Term.index 8] 32 (Query.Sel (Selection.And (Selection.BT (BoolTerm.EQ (Term.index 3) (Term.index 7))) 33 (Selection.BT (BoolTerm.LT (Term.index 0) (Term.index 4)))) 34 (Query.Proj ![Term.index 0, Term.index 1, Term.index 2, Term.index 3, 35 Term.index 5, Term.index 6, Term.index 7, Term.index 8, 36 Term.mul (Term.index 4) (Term.index 9)] 37 (@Query.Prod _ 5 5 10 rfl (Query.Rel 5 "Personnel") (Query.Rel 5 "Personnel"))))) 38 39 /-- Example 11: the rewriting of `q_city` is the traced query. -/ 40 axiom qcity_rewriting : ∀ (K : Type) (hq : qcity.source), 41 Query.rewriting (K := K) qcity hq = qcityRewritten K 42 43 end Lax392996.RewritingExample 44 -
Annotated semantics of the relational algebra
The semantics of a source query on a -instance , for an m-semiring , clause by clause: ; projection and selection act on the data part and carry the annotation along; the cross product annotates by ; the multiset sum adds the two annotated relations; duplicate elimination collapses the copies of a tuple into one, annotated by the -sum of their annotations; and difference keeps every tuple of the left argument, annotated by where is the -sum of the annotations of the copies of in the right argument. The seven claims are the clauses of the paper.
- def✓
Lax392996.AnnotatedSemantics(1st statement) - def✓
Lax392996.AnnotatedSemantics(2nd statement) - def✓
Lax392996.AnnotatedSemantics(3rd statement) - def✓
Lax392996.AnnotatedSemantics(4th statement) - def✓
Lax392996.AnnotatedSemantics(5th statement) - def✓
Lax392996.AnnotatedSemantics(6th statement) - def✓
Lax392996.AnnotatedSemantics(7th statement)
1 import Mathlib.Data.Fin.Tuple.Basic 2 import Mathlib.Data.Multiset.MapFold 3 import Mathlib.Data.Multiset.Count 4 import Mathlib.Data.Multiset.Bind 5 import Lax392996.SemiringsWithMonus 6 import Lax392996.Databases 7 import Lax392996.AnnotatedDatabases 8 import Lax392996.RelationalAlgebra 9 … module docstring, 17 lines 27 28 namespace Lax392996.AnnotatedSemantics 29 30 open Lax392996.SemiringsWithMonus Lax392996.Databases Lax392996.AnnotatedDatabases 31 open Lax392996.RelationalAlgebra 32 33 variable {T : Type} [ValueType T] 34 variable {K : Type} [SemiringWithMonus K] 35 36 @[reducible] def Selection.evalDecidableAnnotated {n : ℕ} (φ : Selection T n) : 37 DecidablePred (λ (ta: AnnotatedTuple T K n) ↦ φ.eval ta.fst) := 38 λ t => match φ.evalDecidable t.fst with 39 | isTrue h => isTrue (by simp [h]) 40 | isFalse h => isFalse (by simp [h]) 41 42 /-- The `⊕`-sum of the annotations of the copies of the data part `u` in an 43 annotated relation. -/ 44 def annotationSum {n : ℕ} (r : Multiset (Tuple T n × K)) (u : Tuple T n) : K := 45 (Multiset.map Prod.snd 46 (@Multiset.filter _ (fun p : Tuple T n × K => p.1 = u) 47 (fun p => instDecidableEqTuple p.1 u) r)).sum 48 49 /-- Grouping of annotated tuples by their data part: each distinct data 50 part once, with the `⊕`-sum of the annotations of its copies. -/ 51 def groupByKey {n : ℕ} (r : Multiset (Tuple T n × K)) : Multiset (Tuple T n × K) := 52 Multiset.map (fun u => (u, annotationSum r u)) (Multiset.dedup (Multiset.map Prod.fst r)) 53 54 /-- Annotated (m-semiring) semantics of a source query. 55 56 The `Diff` case follows ProvSQL: every tuple slot `(u, α)` of `r₁` is kept, 57 with its annotation rewritten to `α ⊖ Σ β` where `Σ β` is the semiring sum of 58 the annotations of all copies of `u` in `r₂`. Duplicate elimination keeps 59 each data part once, annotated by the `⊕`-sum of the annotations of its 60 copies. -/ 61 def Query.evaluateAnnotated {n : ℕ} (q: Query T n) (hq: q.source) (d: AnnotatedDatabase T K) : 62 AnnotatedRelation T K n := match q with 63 | Query.Rel n s => 64 match h : d.find n s with 65 | none => (∅: Multiset (AnnotatedTuple T K n)) 66 | some rn => rn 67 | @Query.Proj _ n m ts q' => 68 let r := evaluateAnnotated q' (Query.source_proj hq rfl) d 69 r.map (λ t ↦ ⟨λ k ↦ (ts k).eval t.fst, t.snd⟩) 70 | Query.Sel φ q => 71 let r := evaluateAnnotated q (Query.source_sel hq rfl) d 72 @Multiset.filter _ (λ ta ↦ φ.eval ta.fst) (Selection.evalDecidableAnnotated φ) r 73 | @Query.Prod _ n₁ n₂ n hn q₁ q₂ => 74 let r₁ := evaluateAnnotated q₁ (Query.source_prod hq rfl).left d 75 let r₂ := evaluateAnnotated q₂ (Query.source_prod hq rfl).right d 76 Multiset.map (λ (x,y) ↦ ⟨ 77 Eq.mp (by simp[hn]; rfl) 78 (Fin.append x.fst y.fst), 79 x.snd*y.snd 80 ⟩) (Multiset.product r₁ r₂) 81 | Query.Sum q₁ q₂ => 82 let r₁ := evaluateAnnotated q₁ (Query.source_sum hq rfl).left d 83 let r₂ := evaluateAnnotated q₂ (Query.source_sum hq rfl).right d 84 r₁+r₂ 85 | Query.Dedup q => 86 let r := evaluateAnnotated q (Query.source_dedup hq rfl) d 87 groupByKey r 88 | Query.Diff q₁ q₂ => 89 let r₁ := evaluateAnnotated q₁ (Query.source_diff hq rfl).left d 90 let r₂ := evaluateAnnotated q₂ (Query.source_diff hq rfl).right d 91 r₁.map 92 λ (u,α) ↦ ⟨u, α - annotationSum r₂ u⟩ 93 | Query.ProvSum _ _ _ => False.elim (by 94 simp[Query.source] at hq 95 ) 96 97 /-- **relation**: `⟪R⟫_Î ≝ Î(R)`. -/ 98 axiom aeval_rel : ∀ {n : ℕ} (R : String) (hq : (Query.Rel n R).source) (d : AnnotatedDatabase T K), 99 Query.evaluateAnnotated (Query.Rel n R) hq d 100 = (d.find n R).getD (∅ : Multiset (AnnotatedTuple T K n)) 101 102 /-- **projection**: the annotation rides along unchanged. -/ 103 axiom aeval_proj : ∀ {n k : ℕ} (ts : Tuple (Term T k) n) (q : Query T k) 104 (hq : (Query.Proj ts q).source) (d : AnnotatedDatabase T K), 105 Query.evaluateAnnotated (Query.Proj ts q) hq d 106 = (Query.evaluateAnnotated q (Query.source_proj hq rfl) d).map 107 (fun p => ⟨fun l => (ts l).eval p.fst, p.snd⟩) 108 109 /-- **selection**: the predicate reads the data part only. -/ 110 axiom aeval_sel : ∀ {n : ℕ} (φ : Selection T n) (q : Query T n) (hq : (Query.Sel φ q).source) 111 (d : AnnotatedDatabase T K), 112 Query.evaluateAnnotated (Query.Sel φ q) hq d 113 = @Multiset.filter _ (fun p => φ.eval p.fst) (Selection.evalDecidableAnnotated φ) 114 (Query.evaluateAnnotated q (Query.source_sel hq rfl) d) 115 116 /-- **cross product**: annotations multiply, `α ⊗ β`. -/ 117 axiom aeval_prod : ∀ {n k₁ k₂ : ℕ} {hn : k₁ + k₂ = n} (q₁ : Query T k₁) (q₂ : Query T k₂) 118 (hq : (Query.Prod (hn := hn) q₁ q₂).source) (d : AnnotatedDatabase T K), 119 Query.evaluateAnnotated (Query.Prod (hn := hn) q₁ q₂) hq d 120 = Multiset.map 121 (fun (xy : AnnotatedTuple T K k₁ × AnnotatedTuple T K k₂) => 122 (⟨Eq.mp (by simp [hn]; rfl) (Fin.append xy.1.fst xy.2.fst), xy.1.snd * xy.2.snd⟩ : 123 AnnotatedTuple T K n)) 124 (Multiset.product (Query.evaluateAnnotated q₁ (Query.source_prod hq rfl).left d) 125 (Query.evaluateAnnotated q₂ (Query.source_prod hq rfl).right d)) 126 127 /-- **multiset sum**: the two annotated relations are added. -/ 128 axiom aeval_sum : ∀ {n : ℕ} (q₁ q₂ : Query T n) (hq : (Query.Sum q₁ q₂).source) 129 (d : AnnotatedDatabase T K), 130 Query.evaluateAnnotated (Query.Sum q₁ q₂) hq d 131 = Query.evaluateAnnotated q₁ (Query.source_sum hq rfl).left d 132 + Query.evaluateAnnotated q₂ (Query.source_sum hq rfl).right d 133 134 /-- **duplicate elimination**: the copies of a tuple are collapsed into one, 135 annotated by the `⊕`-sum of their annotations. -/ 136 axiom aeval_dedup : ∀ {n : ℕ} (q : Query T n) (hq : (Query.Dedup q).source) 137 (d : AnnotatedDatabase T K), 138 Query.evaluateAnnotated (Query.Dedup q) hq d 139 = groupByKey (Query.evaluateAnnotated q (Query.source_dedup hq rfl) d) 140 141 /-- **multiset difference**: a tuple of the left argument keeps its slot, with 142 annotation `α ⊖ Σβ` where `Σβ` is the `⊕`-sum of the annotations of its copies 143 in the right argument. -/ 144 axiom aeval_diff : ∀ {n : ℕ} (q₁ q₂ : Query T n) (hq : (Query.Diff q₁ q₂).source) 145 (d : AnnotatedDatabase T K), 146 Query.evaluateAnnotated (Query.Diff q₁ q₂) hq d 147 = (Query.evaluateAnnotated q₁ (Query.source_diff hq rfl).left d).map 148 (fun (u, a) => 149 (u, a - annotationSum (Query.evaluateAnnotated q₂ (Query.source_diff hq rfl).right d) u)) 150 151 end Lax392996.AnnotatedSemantics 152 - def✓
-
The Personnel example, annotated
The -instance of the paper's Example 9, for : the tuple with id of annotated by the variable . The annotated answer has the three cities as data parts, and their annotations are the Boolean functions for Nairobi, for Paris and for Beijing, the claims being stated pointwise on the valuations of . Variables are numbered from 0 here, from 1 in the paper.
- exa✓
Lax392996.ProvenanceExample(1st statement) - exa✓
Lax392996.ProvenanceExample(2nd statement) - exa✓
Lax392996.ProvenanceExample(3rd statement) - exa✓
Lax392996.ProvenanceExample(4th statement)
1 import Mathlib.Data.Fin.VecNotation 2 import Mathlib.Data.Prod.Lex 3 import Lax392996.SemiringsWithMonus 4 import Lax392996.BooleanFunctions 5 import Lax392996.Databases 6 import Lax392996.AnnotatedDatabases 7 import Lax392996.RelationalAlgebra 8 import Lax392996.AnnotatedSemantics 9 import Lax392996.ProbabilisticDatabases 10 import Lax392996.PersonnelExample 11 … module docstring, 15 lines 27 28 namespace Lax392996.ProvenanceExample 29 30 open Lax392996.SemiringsWithMonus Lax392996.BooleanFunctions Lax392996.Databases 31 open Lax392996.AnnotatedDatabases Lax392996.RelationalAlgebra Lax392996.AnnotatedSemantics 32 open Lax392996.ProbabilisticDatabases Lax392996.PersonnelExample 33 34 /-- The variable `t_i`, as the Boolean function reading it off a valuation. -/ 35 def t (i : Fin 7) : BoolFunc (Fin 7) := fun ν => ν i 36 37 /-- `Personnel` annotated: the tuple with id `i` carries `t_i`. -/ 38 def personnelB : AnnotatedRelation String (BoolFunc (Fin 7)) 4 := Multiset.ofList [ 39 toLex (!["1", "Juma", "Director", "Nairobi"], t 0), 40 toLex (!["2", "Paul", "Janitor", "Nairobi"], t 1), 41 toLex (!["3", "David", "Analyst", "Paris"], t 2), 42 toLex (!["4", "Ellen", "Field agent", "Beijing"], t 3), 43 toLex (!["5", "Aaheli", "Double agent", "Paris"], t 4), 44 toLex (!["6", "Nancy", "HR", "Paris"], t 5), 45 toLex (!["7", "Jing", "Analyst", "Beijing"], t 6)] 46 47 /-- The `B[X]`-instance `Î`. -/ 48 def instanceB : AnnotatedDatabase String (BoolFunc (Fin 7)) := [("Personnel", ⟨4, personnelB⟩)] 49 50 /-- Example 9, the data: the annotated answer has the three cities as data parts. -/ 51 axiom data_answer : ∀ hq : qcity.source, 52 Multiset.map Prod.fst (Query.evaluateAnnotated qcity hq instanceB) 53 = Multiset.ofList [!["Nairobi"], !["Paris"], !["Beijing"]] 54 55 /-- Example 9, Nairobi: annotated by `t_1 ∧ t_2`. -/ 56 axiom nairobi_annotation : ∀ (hq : qcity.source) (ν : Fin 7 → Bool), 57 tupleAnnotation (Query.evaluateAnnotated qcity hq instanceB) !["Nairobi"] ν = (ν 0 && ν 1) 58 59 /-- Example 9, Paris: annotated by `(t_3 ∧ t_5) ∨ (t_5 ∧ t_6) ∨ (t_3 ∧ t_6)`. -/ 60 axiom paris_annotation : ∀ (hq : qcity.source) (ν : Fin 7 → Bool), 61 tupleAnnotation (Query.evaluateAnnotated qcity hq instanceB) !["Paris"] ν 62 = ((ν 2 && ν 4) || (ν 4 && ν 5) || (ν 2 && ν 5)) 63 64 /-- Example 9, Beijing: annotated by `t_4 ∧ t_7`. -/ 65 axiom beijing_annotation : ∀ (hq : qcity.source) (ν : Fin 7 → Bool), 66 tupleAnnotation (Query.evaluateAnnotated qcity hq instanceB) !["Beijing"] ν = (ν 3 && ν 6) 67 68 end Lax392996.ProvenanceExample 69 - exa✓
-
Annotated relations and databases
For an m-semiring , a -relation of arity is a finite multiset of -tuples each carrying an annotation in , and a -instance maps each relation name, at its arity, to a -relation: the two claims record that the definitions are these ones. An annotated tuple of arity also reads as a plain tuple of arity over , its annotation in the last column, which extends to relations and instances, and a composite tuple reads back as an annotated one; this composite reading is what the rewriting of the paper targets. For it, is made a value type, with data values below annotations and the annotations compared through the alternative linear order of .
1 import Mathlib.Data.Prod.Lex 2 import Mathlib.Data.Fin.Tuple.Basic 3 import Mathlib.Data.Fin.VecNotation 4 import Mathlib.Data.Multiset.Basic 5 import Lax392996.Databases 6 import Lax392996.SemiringsWithMonus 7 … module docstring, 18 lines 26 27 namespace Lax392996.AnnotatedDatabases 28 29 open Lax392996.Databases Lax392996.SemiringsWithMonus 30 31 universe u 32 33 variable {T : Type} [ValueType T] {K : Type} [Zero K] {n : ℕ} 34 35 /-- An annotated tuple: a tuple paired with an annotation, ordered 36 lexicographically. -/ 37 abbrev AnnotatedTuple (T : Type) (K : Type u) (n: ℕ) := Tuple T n ×ₗ K 38 39 /-- A `K`-relation of arity `arity`: a finite multiset of annotated tuples. -/ 40 def AnnotatedRelation (T : Type) (K : Type u) (arity: ℕ) := Multiset (AnnotatedTuple T K arity) 41 42 instance instAddAnnotatedRelation {arity : ℕ} : Add (AnnotatedRelation T K arity) := by 43 show Add (Multiset (AnnotatedTuple T K arity)) 44 infer_instance 45 46 /-- A `K`-instance: a list of named annotated relations, each with its arity. -/ 47 def AnnotatedDatabase (T : Type) (K : Type u) := List (String × Σ n, AnnotatedRelation T K n) 48 49 /-- The annotated relation named `s` of arity `n` in a `K`-instance, if any. -/ 50 def AnnotatedDatabase.find (n: ℕ) (s: String) (d: AnnotatedDatabase T K) : 51 Option (AnnotatedRelation T K n) := 52 let rec f 53 | [] => none 54 | (s',rn)::tl => if h: n = rn.fst ∧ s =s' then some (Eq.mp (by rw[h.left]) rn.snd) else f tl 55 f d 56 57 /-- The composite reading of an annotated tuple: the annotation becomes a 58 last column over `T ⊕ K`. -/ 59 def AnnotatedTuple.toComposite (p: AnnotatedTuple T K n) := 60 Fin.append (λ k: Fin n ↦ Sum.inl (p.fst k)) ![Sum.inr p.snd] 61 62 /-- The annotated tuple a composite tuple reads as: the data values from 63 its first `n` columns, the annotation from its last one. -/ 64 def Tuple.fromComposite (t: Tuple (T⊕K) (n+1)) : AnnotatedTuple T K n := 65 ( 66 λ (k: Fin n) ↦ match t (k.castLE (by simp)) with | Sum.inl x => x | Sum.inr _ => 0, 67 match t (Fin.last n) with | Sum.inl _ => 0 | Sum.inr x => x 68 ) 69 70 /-- The composite reading of an annotated relation. -/ 71 def AnnotatedRelation.toComposite (ar: AnnotatedRelation T K n): 72 Relation (T⊕K) (n+1) := 73 ar.map λ p ↦ p.toComposite 74 75 /-- The composite reading of a `K`-instance: a plain database over `T ⊕ K`. -/ 76 def AnnotatedDatabase.toComposite (d: AnnotatedDatabase T K): Database (T⊕K) := 77 d.map λ (s, ⟨n',r⟩) ↦ (s, ⟨n'+1,r.toComposite⟩) 78 79 /-- `V ⊕ K` is a value type: data values are below annotations, and 80 annotations are compared through the alternative linear order of `K`. -/ 81 instance instValueTypeSumOfHasAltLinearOrderOfSemiringWithMonus {V K : Type} 82 [ValueType V] [HasAltLinearOrder K] [SemiringWithMonus K] : ValueType (V⊕K) where 83 zero := Sum.inr 0 84 85 add a b := match a,b with 86 | Sum.inl a', Sum.inl b' => Sum.inl (a'+b') 87 | Sum.inr a', Sum.inr b' => Sum.inr (a'+b') 88 | Sum.inl a', Sum.inr b' => Sum.inl (a') 89 | Sum.inr a', Sum.inl b' => Sum.inl (b') 90 91 sub a b := match a,b with 92 | Sum.inl a', Sum.inl b' => Sum.inl (a'-b') 93 | Sum.inr a', Sum.inr b' => Sum.inr (a'-b') 94 | Sum.inl a', Sum.inr b' => Sum.inl (a') 95 | Sum.inr a', Sum.inl b' => Sum.inl (b') 96 97 mul a b := match a,b with 98 | Sum.inl a', Sum.inl b' => Sum.inl (a'*b') 99 | Sum.inr a', Sum.inr b' => Sum.inr (a'*b') 100 | Sum.inl a', Sum.inr b' => Sum.inl (a') 101 | Sum.inr a', Sum.inl b' => Sum.inl (b') 102 103 add_assoc a b c := by 104 cases a <;> cases b <;> cases c <;> simp[(· + ·)] <;> exact add_assoc _ _ _ 105 106 add_comm a b := by 107 cases a <;> cases b <;> simp[(· + ·)] <;> exact add_comm _ _ 108 109 le a b := match a,b with 110 | Sum.inl a', Sum.inl b' => a'≤b' 111 | Sum.inr a', Sum.inr b' => HasAltLinearOrder.altOrder.le a' b' 112 | Sum.inl a', Sum.inr b' => True 113 | Sum.inr a', Sum.inl b' => False 114 115 le_refl a := by 116 cases a <;> simp 117 118 le_antisymm a b := by 119 cases a <;> cases b <;> simp 120 . exact le_antisymm 121 . exact HasAltLinearOrder.altOrder.le_antisymm _ _ 122 123 le_trans a b c := by 124 cases a <;> cases b <;> cases c <;> simp 125 . exact le_trans 126 . exact HasAltLinearOrder.altOrder.le_trans _ _ _ 127 128 le_total a b := by 129 cases a <;> cases b <;> simp 130 . exact le_total _ _ 131 . next x y => 132 exact HasAltLinearOrder.altOrder.le_total x y 133 134 toDecidableLE := 135 λ a b ↦ match a, b with 136 | Sum.inl a', Sum.inl b' => inferInstance 137 | Sum.inr a', Sum.inr b' => inferInstance 138 | Sum.inl a', Sum.inr b' => isTrue (trivial) 139 | Sum.inr a', Sum.inl b' => isFalse (id) 140 141 /-- A `K`-relation of arity `n` is a multiset of `n`-tuples paired with an 142 annotation. -/ 143 axiom annotated_relation_eq : AnnotatedRelation T K n = Multiset (Tuple T n ×ₗ K) 144 145 /-- A `K`-instance answers a relation name, at an arity, with a `K`-relation. -/ 146 axiom annotated_database_lookup : 147 ∀ (R : String) (d : AnnotatedDatabase T K), 148 (AnnotatedDatabase.find n R d : Option (AnnotatedRelation T K n)) = d.find n R 149 150 end Lax392996.AnnotatedDatabases 151 -
The counting semiring is an m-semiring
The counting semiring is an m-semiring: its natural order is the usual order on natural numbers, its monus is truncated subtraction, and its operator is the support indicator, on and elsewhere. Unlike most provenance semirings it is neither idempotent nor absorptive. Its usual order also serves as the alternative linear order that lets counts share a column with data values.
1 import Mathlib.Algebra.Order.Ring.Defs 2 import Mathlib.Algebra.Order.Ring.Canonical 3 import Mathlib.Algebra.Order.Group.Nat 4 import Mathlib.Algebra.Order.Ring.Nat 5 import Lax392996.SemiringsWithMonus 6 … module docstring, 12 lines 19 20 namespace Lax392996.CountingSemiring 21 22 open Lax392996.SemiringsWithMonus 23 24 /-- The support indicator: `0 ↦ 0`, positive `↦ 1`. -/ 25 def Nat.deltaInd (n : ℕ) : ℕ := if n = 0 then 0 else 1 26 27 /-- `ℕ` is an m-semiring: the natural order is the usual one, the monus is 28 truncated subtraction, and `δ` is the support indicator. -/ 29 instance instSemiringWithMonusNat : SemiringWithMonus ℕ where 30 monus_spec := by 31 intro a b c 32 omega 33 delta := Nat.deltaInd 34 delta_zero := rfl 35 delta_natCast_pos := by 36 intro n hn 37 simp [Nat.deltaInd, Nat.pos_iff_ne_zero.mp hn] 38 delta_absorb := by 39 intro a b 40 by_cases ha : a = 0 41 · simp [ha, Nat.deltaInd] 42 · simp [Nat.deltaInd, ha] 43 44 instance instHasAltLinearOrderNat : HasAltLinearOrder ℕ where 45 altOrder := inferInstance 46 47 end Lax392996.CountingSemiring 48 -
Boolean functions as an m-semiring
The m-semiring of Boolean functions over a set of Boolean variables: elements are the functions , with pointwise as , pointwise as , the constant functions and as and , pointwise implication as the natural order and as ; is the identity. Equality of two Boolean functions is decidable classically, which is what the annotated semantics requires of an annotation type.
1 import Mathlib.Algebra.Ring.Defs 2 import Mathlib.Order.Basic 3 import Lax392996.SemiringsWithMonus 4 … module docstring, 14 lines 19 20 namespace Lax392996.BooleanFunctions 21 22 open Lax392996.SemiringsWithMonus 23 24 variable {X : Type} 25 26 /-- The type of Boolean functions over Boolean assignments to `X`: 27 `(X → Bool) → Bool` with pointwise operations. -/ 28 def BoolFunc (X : Type) := (X → Bool) → Bool 29 30 instance instZeroBoolFunc : Zero (BoolFunc X) := ⟨λ _ ↦ False⟩ 31 32 instance instAddBoolFunc : Add (BoolFunc X) := ⟨λ f₁ f₂ ν ↦ (f₁ ν) || (f₂ ν)⟩ 33 34 instance instOneBoolFunc : One (BoolFunc X) := ⟨λ _ ↦ True⟩ 35 36 instance instMulBoolFunc : Mul (BoolFunc X) := ⟨λ f₁ f₂ ν ↦ (f₁ ν) && (f₂ ν)⟩ 37 38 instance instLEBoolFunc : LE (BoolFunc X) := ⟨λ f₁ f₂ ↦ ∀ ν : X → Bool, (f₁ ν) ≤ (f₂ ν)⟩ 39 40 instance instSubBoolFunc : Sub (BoolFunc X) := ⟨λ f₁ f₂ ν ↦ (f₁ ν) && !(f₂ ν)⟩ 41 42 instance instCommSemiringBoolFunc : CommSemiring (BoolFunc X) where 43 add_assoc := by 44 intro a b c 45 simp[(· + ·),Add.add] 46 apply funext 47 intro x 48 exact Bool.or_assoc _ _ _ 49 50 add_comm := by 51 intro a b 52 simp[(· + ·),Add.add] 53 apply funext 54 intro x 55 exact Bool.or_comm _ _ 56 57 zero_add := by tauto 58 59 add_zero := by 60 simp[(· + ·),Add.add] 61 intro a 62 apply funext 63 simp 64 tauto 65 66 nsmul := nsmulRec 67 68 left_distrib := by 69 simp[(· + ·),Add.add,(· * ·),Mul.mul] 70 intro a b c 71 apply funext 72 intro x 73 exact Bool.and_or_distrib_left _ _ _ 74 75 right_distrib := by 76 simp[(· + ·),Add.add,(· * ·),Mul.mul] 77 intro a b c 78 apply funext 79 intro x 80 exact Bool.and_or_distrib_right _ _ _ 81 82 zero_mul := by tauto 83 84 mul_zero := by 85 simp[(· * ·),Mul.mul] 86 intro a 87 apply funext 88 simp 89 tauto 90 91 mul_assoc := by 92 intro a b c 93 simp[(· * ·),Mul.mul] 94 apply funext 95 intro x 96 exact Bool.and_assoc _ _ _ 97 98 mul_comm := by 99 intro a b 100 simp[(· * ·),Mul.mul] 101 apply funext 102 intro x 103 exact Bool.and_comm _ _ 104 105 one_mul := by tauto 106 107 mul_one := by 108 simp[(· * ·),Mul.mul] 109 intro a 110 apply funext 111 simp 112 tauto 113 114 /-- `BoolFunc X` is a commutative m-semiring with pointwise `||` as addition, 115 pointwise `&&` as multiplication, and pointwise implication as natural order. -/ 116 instance instSemiringWithMonusBoolFunc : SemiringWithMonus (BoolFunc X) where 117 le_refl := by tauto 118 119 le_trans := by tauto 120 121 le_antisymm := by 122 simp[(· ≤ ·)] 123 intro a b hab hba 124 apply funext 125 intro ν 126 exact Bool.le_antisymm (hab ν) (hba ν) 127 128 le_self_add := by 129 simp[(· + ·),Add.add,(· ≤ ·)] 130 tauto 131 132 le_add_self := by 133 simp[(· + ·),Add.add,(· ≤ ·)] 134 tauto 135 136 add_le_add_left := by 137 simp[(· + ·),Add.add,(· ≤ ·)] 138 tauto 139 140 exists_add_of_le := by 141 simp[(· + ·),Add.add,(· ≤ ·)] 142 intro a b h 143 use b 144 apply funext 145 intro x 146 cases ha : a x 147 . tauto 148 . apply (h x) ha 149 150 monus_spec := by 151 intro a b c 152 simp[(· + ·),Add.add,(· ≤ ·),(· - ·),Sub.sub] 153 apply Iff.intro 154 . intro h ν ha 155 cases hb : b ν <;> simp 156 . exact h ν ha hb 157 . intro h ν ha hb 158 have h' : b ν = true ∨ c ν = true := h ν ha 159 simp[hb] at h' 160 exact h' 161 162 delta := id 163 delta_zero := rfl 164 delta_natCast_pos := by 165 have hidem : ∀ a : BoolFunc X, a + a = a := fun a => funext fun ν => by 166 show (a ν || a ν) = a ν 167 simp 168 have hcast : ∀ {n : ℕ}, 0 < n → (n : BoolFunc X) = 1 := by 169 intro n hn 170 induction n with 171 | zero => omega 172 | succ m ih => 173 rcases Nat.eq_zero_or_pos m with hm | hm 174 · rw [hm]; simp 175 · rw [Nat.cast_succ, ih hm, hidem 1] 176 intro n hn 177 exact hcast hn 178 delta_absorb := fun a b => funext fun ν => by 179 show (a ν && (a ν || b ν)) = a ν 180 cases a ν <;> cases b ν <;> rfl 181 182 /-- For finite `X`, equality of Boolean functions `(X → Bool) → Bool` is 183 decidable in principle, the function space being finite. The classical 184 decidability instance is what the annotated semantics, which requires 185 `[DecidableEq K]`, is invoked with for `K = BoolFunc X`. -/ 186 noncomputable instance instDecidableEqBoolFunc : DecidableEq (BoolFunc X) := 187 Classical.decEq _ 188 189 end Lax392996.BooleanFunctions 190 -
Why-provenance is an m-semiring
For a set , is an m-semiring, where : an element is a family of witness sets, addition is union of families, multiplication is pairwise union of witnesses, and the monus is set difference of families, with the natural order being inclusion. The instance is built here, and the claims pin each operation to the stated one: exhibiting an m-semiring structure on is only half of the proposition, the operations have to be the right ones.
- thm✓
Lax392996.WhyProvenance(1st statement) - thm✓
Lax392996.WhyProvenance(2nd statement) - thm✓
Lax392996.WhyProvenance(3rd statement) - thm✓
Lax392996.WhyProvenance(4th statement) - thm✓
Lax392996.WhyProvenance(5th statement) - thm✓
Lax392996.WhyProvenance(6th statement)
1 import Mathlib.Data.Set.Basic 2 import Mathlib.Data.Set.Insert 3 import Mathlib.Algebra.Ring.Defs 4 import Lax392996.SemiringsWithMonus 5 … module docstring, 14 lines 20 21 namespace Lax392996.WhyProvenance 22 23 open Lax392996.SemiringsWithMonus 24 25 variable {α : Type} 26 27 /-- Why-provenance over `α`: a family of sets of witnesses. -/ 28 @[ext] 29 structure Why (α: Type) where 30 carrier : Set (Set α) 31 32 instance instCoeWhySet : Coe (Why α) (Set (Set α)) := ⟨Why.carrier⟩ 33 34 instance instZeroWhy : Zero (Why α) where 35 zero := ⟨∅⟩ 36 37 instance instAddWhy : Add (Why α) where 38 add a b := ⟨a ∪ b⟩ 39 40 /-- Pairwise union of witnesses, the multiplication of `Why α`. -/ 41 def why_mul (a b: Why α) : Why α := 42 ⟨{ z : Set α | ∃ x y : Set α, x ∈ a.carrier ∧ y ∈ b.carrier ∧ z = x ∪ y}⟩ 43 44 instance instCommSemiringWhy : CommSemiring (Why α) where 45 one := ⟨{∅}⟩ 46 mul := why_mul 47 48 add_assoc := by 49 intro a b c 50 simp [HAdd.hAdd, Add.add] 51 exact Set.union_assoc _ _ _ 52 53 zero_add := by 54 intro a 55 show ⟨(⟨∅⟩ : Why α).carrier ∪ a.carrier⟩ = a 56 simp 57 58 add_zero := by 59 intro a 60 show ⟨a.carrier ∪ (⟨∅⟩ : Why α).carrier⟩ = a 61 simp 62 63 add_comm := by 64 intro a b 65 simp [HAdd.hAdd, Add.add] 66 exact Set.union_comm _ _ 67 68 mul_assoc := by 69 intro a b c 70 unfold why_mul 71 ext w 72 simp [HMul.hMul] 73 apply Iff.intro 74 . intro h 75 obtain ⟨xa, xb, h₁, h₂⟩ := h 76 obtain ⟨hxa, hxb⟩ := h₁ 77 obtain ⟨xc, hxc, hw⟩ := h₂ 78 use xa, hxa, xb, xc 79 constructor 80 . use hxb, hxc 81 . simp[hw, Set.union_assoc] 82 83 . intro h 84 obtain ⟨xa, hxa, xb, xc, hxbc, hw⟩ := h 85 use xa, xb 86 constructor 87 . use hxa, hxbc.1 88 . use xc, hxbc.2 89 simp[hw, Set.union_assoc] 90 91 one_mul := by 92 intro a 93 show why_mul (⟨{∅}⟩: Why α) a = a 94 unfold why_mul 95 simp 96 97 mul_one := by 98 intro a 99 show why_mul a (⟨{∅}⟩: Why α) = a 100 unfold why_mul 101 simp 102 103 zero_mul := by 104 intro a 105 show why_mul (⟨∅⟩: Why α) a = (⟨∅⟩: Why α) 106 unfold why_mul 107 simp 108 109 mul_zero := by 110 intro a 111 show why_mul a (⟨∅⟩: Why α) = (⟨∅⟩: Why α) 112 unfold why_mul 113 simp 114 115 mul_comm := by 116 intro a b 117 show why_mul a b = why_mul b a 118 unfold why_mul 119 ext z 120 simp 121 apply Iff.intro 122 . intro h 123 obtain ⟨x, hx, y, hy, hz⟩ := h 124 use y, hy, x, hx 125 simp[hz, Set.union_comm] 126 . intro h 127 obtain ⟨y, hy, x, hx, hz⟩ := h 128 use x, hx, y, hy 129 simp[hz, Set.union_comm] 130 131 left_distrib := by 132 intro a b c 133 show why_mul a ⟨b ∪ c⟩ = ⟨(why_mul a b) ∪ (why_mul a c)⟩ 134 unfold why_mul 135 ext z 136 simp 137 apply Iff.intro 138 . intro h 139 obtain ⟨x, hx, y, hy, hz⟩ := h 140 cases hy with 141 | inl hy' => 142 apply Or.inl 143 use x, hx, y, hy' 144 | inr hy' => 145 apply Or.inr 146 use x, hx, y, hy' 147 . intro h 148 cases h with 149 | inl h' => 150 obtain ⟨x, hx, y, hy, hz⟩ := h' 151 use x, hx, y 152 simp[hy, hz] 153 | inr h' => 154 obtain ⟨x, hx, y, hy, hz⟩ := h' 155 use x, hx, y 156 simp[hy, hz] 157 158 right_distrib := by 159 intro a b c 160 show why_mul ⟨a ∪ b⟩ c = ⟨(why_mul a c) ∪ (why_mul b c)⟩ 161 unfold why_mul 162 simp 163 ext z 164 simp 165 apply Iff.intro 166 . intro h 167 obtain ⟨x, hx, y, hy, hz⟩ := h 168 cases hx with 169 | inl hx' => 170 apply Or.inl 171 use x, hx', y, hy 172 | inr hx' => 173 apply Or.inr 174 use x, hx', y, hy 175 . intro h 176 cases h with 177 | inl h' => 178 obtain ⟨x, hx, y, hy, hz⟩ := h' 179 use x 180 simp[hx] 181 use y 182 | inr h' => 183 obtain ⟨x, hx, y, hy, hz⟩ := h' 184 use x 185 simp[hx] 186 use y 187 188 nsmul := nsmulRec 189 190 /-- The support indicator: `𝟘` on the empty family, `𝟙` on any nonempty 191 one. This is the `δ` of `Why α`. -/ 192 def Why.deltaInd (a : Why α) : Why α := 193 ⟨{s | s = ∅ ∧ a.carrier.Nonempty}⟩ 194 195 /-- Why-provenance is a semiring with monus: `∖` is set difference on the outer 196 level, `2^(2^X)` ordered by inclusion. -/ 197 instance instSemiringWithMonusWhy : SemiringWithMonus (Why α) where 198 le a b := a.carrier ⊆ b.carrier 199 le_refl := by simp 200 le_trans := by 201 intro a b c ha hb x hx 202 exact hb (ha hx) 203 204 le_antisymm := by 205 intro a b ha hb 206 ext x 207 apply Iff.intro 208 . exact fun a ↦ ha (hb (ha a)) 209 . exact fun a ↦ hb (ha (hb a)) 210 211 add_le_add_left := by 212 simp[HAdd.hAdd,Add.add] 213 intro a b hab c x hx 214 simp 215 apply Or.inl 216 exact hab hx 217 218 add_le_add_right := by 219 simp[HAdd.hAdd,Add.add] 220 intro a b hab c x hx 221 simp 222 apply Or.inr 223 exact hab hx 224 225 exists_add_of_le := by 226 intro a b hab 227 simp[HAdd.hAdd,Add.add] 228 use ⟨b.carrier \ a.carrier⟩ 229 ext x 230 simp 231 intro hx 232 exact hab hx 233 234 le_self_add := by 235 intro a b x hx 236 simp[HAdd.hAdd,Add.add] 237 apply Or.inl 238 exact hx 239 240 le_add_self := by 241 intro a b x hx 242 simp[HAdd.hAdd,Add.add] 243 apply Or.inr 244 exact hx 245 246 sub a b := ⟨a.carrier \ b.carrier⟩ 247 monus_spec := by 248 intro a b c 249 simp[HAdd.hAdd,Add.add] 250 show (⟨a.carrier \ b.carrier⟩: Why α).carrier ⊆ c.carrier ↔ a.carrier ⊆ b.carrier ∪ c.carrier 251 apply Iff.intro 252 . intro h x hx 253 by_cases hx' : x ∈ b.carrier 254 . apply Or.inl 255 exact hx' 256 . apply Or.inr 257 have h' : x ∈ a.carrier \ b.carrier := by simp[hx, hx'] 258 exact h h' 259 . intro h x hx 260 simp at hx 261 obtain ⟨ha, hb⟩ := hx 262 have h' : x ∈ b.carrier ∪ c.carrier := h ha 263 simp at h' 264 tauto 265 266 delta := Why.deltaInd 267 delta_zero := by 268 ext z 269 show z ∈ {s | s = ∅ ∧ (∅ : Set (Set α)).Nonempty} ↔ z ∈ (∅ : Set (Set α)) 270 simp 271 delta_natCast_pos := by 272 have hidem : ∀ a : Why α, a + a = a := fun a => by simp [(· + ·), Add.add] 273 have hone : (1 : Why α) ≠ 0 := by 274 intro h 275 have := congrArg Why.carrier h 276 exact Set.singleton_ne_empty (∅ : Set α) this 277 have hcast : ∀ {n : ℕ}, 0 < n → (n : Why α) = 1 := by 278 intro n hn 279 induction n with 280 | zero => omega 281 | succ m ih => 282 rcases Nat.eq_zero_or_pos m with hm | hm 283 · rw [hm]; simp 284 · rw [Nat.cast_succ, ih hm, hidem 1] 285 have hne : ∀ {a : Why α}, a ≠ 0 → Why.deltaInd a = 1 := by 286 intro a h 287 have hnonempty : a.carrier.Nonempty := by 288 rcases Set.eq_empty_or_nonempty a.carrier with he | hne 289 · exact absurd (by ext z; rw [he]; exact Iff.rfl) h 290 · exact hne 291 ext z 292 show z ∈ {s | s = ∅ ∧ a.carrier.Nonempty} ↔ z ∈ ({∅} : Set (Set α)) 293 simp [hnonempty] 294 intro n hn 295 rw [hcast hn, hne hone] 296 delta_absorb := fun a b => by 297 have hzsf : ∀ {a b : Why α}, a + b = 0 → a = 0 := by 298 intro a b h 299 have hc : a.carrier ∪ b.carrier = (∅ : Set (Set α)) := 300 congrArg Why.carrier h 301 have hx : a.carrier = ∅ := by 302 ext w 303 simp only [Set.mem_empty_iff_false, iff_false] 304 intro hw 305 have hmem : w ∈ a.carrier ∪ b.carrier := Set.mem_union_left _ hw 306 rw [hc] at hmem 307 exact hmem 308 ext z 309 rw [hx] 310 exact Iff.rfl 311 have hne : ∀ {a : Why α}, a ≠ 0 → Why.deltaInd a = 1 := by 312 intro a h 313 have hnonempty : a.carrier.Nonempty := by 314 rcases Set.eq_empty_or_nonempty a.carrier with he | hne 315 · exact absurd (by ext z; rw [he]; exact Iff.rfl) h 316 · exact hne 317 ext z 318 show z ∈ {s | s = ∅ ∧ a.carrier.Nonempty} ↔ z ∈ ({∅} : Set (Set α)) 319 simp [hnonempty] 320 by_cases ha : a = 0 321 · rw [ha, zero_mul] 322 · have habne : a + b ≠ 0 := fun h => ha (hzsf h) 323 show a * Why.deltaInd (a + b) = a 324 rw [hne habne, mul_one] 325 326 /-- Why-provenance: `𝟘` is `∅`. -/ 327 axiom Why.zero_carrier : (0 : Why α).carrier = ∅ 328 329 /-- Why-provenance: `𝟙` is `{∅}`. -/ 330 axiom Why.one_carrier : (1 : Why α).carrier = {∅} 331 332 /-- Why-provenance: `⊕` is union of families. -/ 333 axiom Why.add_carrier : ∀ (a b : Why α), (a + b).carrier = a.carrier ∪ b.carrier 334 335 /-- Why-provenance: `⊗` is `⋓`, the pairwise union of witnesses. -/ 336 axiom Why.mul_carrier : ∀ (a b : Why α), 337 (a * b).carrier = {z : Set α | ∃ x y : Set α, x ∈ a.carrier ∧ y ∈ b.carrier ∧ z = x ∪ y} 338 339 /-- Why-provenance: `⊖` is set difference of families. -/ 340 axiom Why.monus_carrier : ∀ (a b : Why α), (a - b).carrier = a.carrier \ b.carrier 341 342 /-- Why-provenance is an m-semiring under exactly those operations. -/ 343 axiom Why.isMSemiring : Nonempty (SemiringWithMonus (Why α)) 344 345 end Lax392996.WhyProvenance 346 - thm✓
-
Semirings with monus
A semiring with monus, or m-semiring, is a semiring with a further binary operation . Here it is axiomatized through the natural order of a canonically ordered semiring, when for some , by the Galois connection ; the three equations of the paper's definition, , and , follow and are the claims of this module. The class also carries the duplicate-eliminating operator of Amsterdamer, Deutch and Tannen (2011), with , and , which the paper's rewriting of aggregation uses. An alternative linear order on an annotation type is bundled separately: it is what makes a type of annotations usable as a value type once data and annotations share a column.
- def✓
Lax392996.SemiringsWithMonus(1st statement) - def✓
Lax392996.SemiringsWithMonus(2nd statement) - def✓
Lax392996.SemiringsWithMonus(3rd statement) - def✓
Lax392996.SemiringsWithMonus(4th statement) - def✓
Lax392996.SemiringsWithMonus(5th statement)
1 import Mathlib.Algebra.Order.Monoid.Canonical.Defs 2 import Mathlib.Algebra.Order.Ring.Defs 3 import Mathlib.Order.Defs.LinearOrder 4 … module docstring, 21 lines 26 27 universe u 28 29 namespace Lax392996.SemiringsWithMonus 30 31 /-- A `SemiringWithMonus` is a naturally ordered semiring 32 with a monus operation that is compatible with the natural order. 33 The semiring is not required to be commutative. 34 35 In addition to monus, the class carries a `δ : α → α` operator subject 36 to three axioms (`delta_zero`, `delta_natCast_pos`, and 37 `delta_absorb`). This is the duplicate-eliminating support 38 operator used to interpret aggregation in the framework of 39 [Amsterdamer, Deutch & Tannen, *Provenance for aggregate queries*][amsterdamer2011aggregate]. -/ 40 class SemiringWithMonus (α : Type) 41 extends Semiring α, PartialOrder α, IsOrderedAddMonoid α, CanonicallyOrderedAdd α, Sub α where 42 monus_spec : ∀ a b c : α, a - b ≤ c ↔ a ≤ b + c 43 /-- Duplicate-eliminating support operator. Sends `0` to `0` and any 44 positive integer iterate of `1` to `1`. -/ 45 delta : α → α 46 /-- `δ` sends `0` to `0`. -/ 47 delta_zero : delta 0 = 0 48 /-- `δ` sends every positive integer iterate of `1` (i.e., every 49 positive natural-number cast) to `1`. -/ 50 delta_natCast_pos : ∀ {n : ℕ}, 0 < n → delta ((n : α)) = 1 51 /-- A δ-guard is absorbed by any multiple of one of its summands: 52 `a ⊗ δ(a ⊕ b) = a`. This is what makes a group-existence factor 53 redundant next to any provenance that already contains an occurrence 54 of the group: `δ` acts as “the group exists” and nothing more. -/ 55 delta_absorb : ∀ (a b : α), a * delta (a + b) = a 56 57 /-- An alternative linear order on a type, used to order annotations when 58 they share a column with data values. -/ 59 class HasAltLinearOrder (α : Type u) where 60 altOrder : LinearOrder α 61 62 /-- The paper's m-semiring axiom (i): `a ⊕ (b ⊖ a) = b ⊕ (a ⊖ b)`. -/ 63 axiom msemiring_axiom_i : ∀ {K : Type} [SemiringWithMonus K] (a b : K), 64 a + (b - a) = b + (a - b) 65 66 /-- The paper's m-semiring axiom (ii): `(a ⊖ b) ⊖ c = a ⊖ (b ⊕ c)`. -/ 67 axiom msemiring_axiom_ii : ∀ {K : Type} [SemiringWithMonus K] (a b c : K), 68 ((a - b) - c) = (a - (b + c)) 69 70 /-- The paper's m-semiring axiom (iii): `a ⊖ a = 𝟘 ⊖ a = 𝟘`. -/ 71 axiom msemiring_axiom_iii : ∀ {K : Type} [SemiringWithMonus K] (a : K), 72 ((a - a) = 0) ∧ (((0 : K) - a) = 0) 73 74 /-- The paper's δ-semiring axiom (i): `δ(𝟘) = 𝟘`. -/ 75 axiom delta_axiom_i : ∀ {K : Type} [SemiringWithMonus K], 76 SemiringWithMonus.delta (0 : K) = 0 77 78 /-- The paper's δ-semiring axiom (ii): `δ(𝟙 ⊕ ⋯ ⊕ 𝟙) = 𝟙`, whatever the 79 positive number of `𝟙`s. -/ 80 axiom delta_axiom_ii : ∀ {K : Type} [SemiringWithMonus K] {j : ℕ}, 0 < j → 81 SemiringWithMonus.delta ((j : K)) = 1 82 83 end Lax392996.SemiringsWithMonus 84 - def✓
-
Why-provenance is an m-semiring
For a set , is an m-semiring, where : an element is a family of witness sets, addition is union of families, multiplication is pairwise union of witnesses, and the monus is set difference of families, with the natural order being inclusion. The instance is built here, and the claims pin each operation to the stated one: exhibiting an m-semiring structure on is only half of the proposition, the operations have to be the right ones.
- thm✓
Lax392996.WhyProvenance(1st statement) - thm✓
Lax392996.WhyProvenance(2nd statement) - thm✓
Lax392996.WhyProvenance(3rd statement) - thm✓
Lax392996.WhyProvenance(4th statement) - thm✓
Lax392996.WhyProvenance(5th statement) - thm✓
Lax392996.WhyProvenance(6th statement)
1 import Mathlib.Data.Set.Basic 2 import Mathlib.Data.Set.Insert 3 import Mathlib.Algebra.Ring.Defs 4 import Lax392996.SemiringsWithMonus 5 … module docstring, 14 lines 20 21 namespace Lax392996.WhyProvenance 22 23 open Lax392996.SemiringsWithMonus 24 25 variable {α : Type} 26 27 /-- Why-provenance over `α`: a family of sets of witnesses. -/ 28 @[ext] 29 structure Why (α: Type) where 30 carrier : Set (Set α) 31 32 instance instCoeWhySet : Coe (Why α) (Set (Set α)) := ⟨Why.carrier⟩ 33 34 instance instZeroWhy : Zero (Why α) where 35 zero := ⟨∅⟩ 36 37 instance instAddWhy : Add (Why α) where 38 add a b := ⟨a ∪ b⟩ 39 40 /-- Pairwise union of witnesses, the multiplication of `Why α`. -/ 41 def why_mul (a b: Why α) : Why α := 42 ⟨{ z : Set α | ∃ x y : Set α, x ∈ a.carrier ∧ y ∈ b.carrier ∧ z = x ∪ y}⟩ 43 44 instance instCommSemiringWhy : CommSemiring (Why α) where 45 one := ⟨{∅}⟩ 46 mul := why_mul 47 48 add_assoc := by 49 intro a b c 50 simp [HAdd.hAdd, Add.add] 51 exact Set.union_assoc _ _ _ 52 53 zero_add := by 54 intro a 55 show ⟨(⟨∅⟩ : Why α).carrier ∪ a.carrier⟩ = a 56 simp 57 58 add_zero := by 59 intro a 60 show ⟨a.carrier ∪ (⟨∅⟩ : Why α).carrier⟩ = a 61 simp 62 63 add_comm := by 64 intro a b 65 simp [HAdd.hAdd, Add.add] 66 exact Set.union_comm _ _ 67 68 mul_assoc := by 69 intro a b c 70 unfold why_mul 71 ext w 72 simp [HMul.hMul] 73 apply Iff.intro 74 . intro h 75 obtain ⟨xa, xb, h₁, h₂⟩ := h 76 obtain ⟨hxa, hxb⟩ := h₁ 77 obtain ⟨xc, hxc, hw⟩ := h₂ 78 use xa, hxa, xb, xc 79 constructor 80 . use hxb, hxc 81 . simp[hw, Set.union_assoc] 82 83 . intro h 84 obtain ⟨xa, hxa, xb, xc, hxbc, hw⟩ := h 85 use xa, xb 86 constructor 87 . use hxa, hxbc.1 88 . use xc, hxbc.2 89 simp[hw, Set.union_assoc] 90 91 one_mul := by 92 intro a 93 show why_mul (⟨{∅}⟩: Why α) a = a 94 unfold why_mul 95 simp 96 97 mul_one := by 98 intro a 99 show why_mul a (⟨{∅}⟩: Why α) = a 100 unfold why_mul 101 simp 102 103 zero_mul := by 104 intro a 105 show why_mul (⟨∅⟩: Why α) a = (⟨∅⟩: Why α) 106 unfold why_mul 107 simp 108 109 mul_zero := by 110 intro a 111 show why_mul a (⟨∅⟩: Why α) = (⟨∅⟩: Why α) 112 unfold why_mul 113 simp 114 115 mul_comm := by 116 intro a b 117 show why_mul a b = why_mul b a 118 unfold why_mul 119 ext z 120 simp 121 apply Iff.intro 122 . intro h 123 obtain ⟨x, hx, y, hy, hz⟩ := h 124 use y, hy, x, hx 125 simp[hz, Set.union_comm] 126 . intro h 127 obtain ⟨y, hy, x, hx, hz⟩ := h 128 use x, hx, y, hy 129 simp[hz, Set.union_comm] 130 131 left_distrib := by 132 intro a b c 133 show why_mul a ⟨b ∪ c⟩ = ⟨(why_mul a b) ∪ (why_mul a c)⟩ 134 unfold why_mul 135 ext z 136 simp 137 apply Iff.intro 138 . intro h 139 obtain ⟨x, hx, y, hy, hz⟩ := h 140 cases hy with 141 | inl hy' => 142 apply Or.inl 143 use x, hx, y, hy' 144 | inr hy' => 145 apply Or.inr 146 use x, hx, y, hy' 147 . intro h 148 cases h with 149 | inl h' => 150 obtain ⟨x, hx, y, hy, hz⟩ := h' 151 use x, hx, y 152 simp[hy, hz] 153 | inr h' => 154 obtain ⟨x, hx, y, hy, hz⟩ := h' 155 use x, hx, y 156 simp[hy, hz] 157 158 right_distrib := by 159 intro a b c 160 show why_mul ⟨a ∪ b⟩ c = ⟨(why_mul a c) ∪ (why_mul b c)⟩ 161 unfold why_mul 162 simp 163 ext z 164 simp 165 apply Iff.intro 166 . intro h 167 obtain ⟨x, hx, y, hy, hz⟩ := h 168 cases hx with 169 | inl hx' => 170 apply Or.inl 171 use x, hx', y, hy 172 | inr hx' => 173 apply Or.inr 174 use x, hx', y, hy 175 . intro h 176 cases h with 177 | inl h' => 178 obtain ⟨x, hx, y, hy, hz⟩ := h' 179 use x 180 simp[hx] 181 use y 182 | inr h' => 183 obtain ⟨x, hx, y, hy, hz⟩ := h' 184 use x 185 simp[hx] 186 use y 187 188 nsmul := nsmulRec 189 190 /-- The support indicator: `𝟘` on the empty family, `𝟙` on any nonempty 191 one. This is the `δ` of `Why α`. -/ 192 def Why.deltaInd (a : Why α) : Why α := 193 ⟨{s | s = ∅ ∧ a.carrier.Nonempty}⟩ 194 195 /-- Why-provenance is a semiring with monus: `∖` is set difference on the outer 196 level, `2^(2^X)` ordered by inclusion. -/ 197 instance instSemiringWithMonusWhy : SemiringWithMonus (Why α) where 198 le a b := a.carrier ⊆ b.carrier 199 le_refl := by simp 200 le_trans := by 201 intro a b c ha hb x hx 202 exact hb (ha hx) 203 204 le_antisymm := by 205 intro a b ha hb 206 ext x 207 apply Iff.intro 208 . exact fun a ↦ ha (hb (ha a)) 209 . exact fun a ↦ hb (ha (hb a)) 210 211 add_le_add_left := by 212 simp[HAdd.hAdd,Add.add] 213 intro a b hab c x hx 214 simp 215 apply Or.inl 216 exact hab hx 217 218 add_le_add_right := by 219 simp[HAdd.hAdd,Add.add] 220 intro a b hab c x hx 221 simp 222 apply Or.inr 223 exact hab hx 224 225 exists_add_of_le := by 226 intro a b hab 227 simp[HAdd.hAdd,Add.add] 228 use ⟨b.carrier \ a.carrier⟩ 229 ext x 230 simp 231 intro hx 232 exact hab hx 233 234 le_self_add := by 235 intro a b x hx 236 simp[HAdd.hAdd,Add.add] 237 apply Or.inl 238 exact hx 239 240 le_add_self := by 241 intro a b x hx 242 simp[HAdd.hAdd,Add.add] 243 apply Or.inr 244 exact hx 245 246 sub a b := ⟨a.carrier \ b.carrier⟩ 247 monus_spec := by 248 intro a b c 249 simp[HAdd.hAdd,Add.add] 250 show (⟨a.carrier \ b.carrier⟩: Why α).carrier ⊆ c.carrier ↔ a.carrier ⊆ b.carrier ∪ c.carrier 251 apply Iff.intro 252 . intro h x hx 253 by_cases hx' : x ∈ b.carrier 254 . apply Or.inl 255 exact hx' 256 . apply Or.inr 257 have h' : x ∈ a.carrier \ b.carrier := by simp[hx, hx'] 258 exact h h' 259 . intro h x hx 260 simp at hx 261 obtain ⟨ha, hb⟩ := hx 262 have h' : x ∈ b.carrier ∪ c.carrier := h ha 263 simp at h' 264 tauto 265 266 delta := Why.deltaInd 267 delta_zero := by 268 ext z 269 show z ∈ {s | s = ∅ ∧ (∅ : Set (Set α)).Nonempty} ↔ z ∈ (∅ : Set (Set α)) 270 simp 271 delta_natCast_pos := by 272 have hidem : ∀ a : Why α, a + a = a := fun a => by simp [(· + ·), Add.add] 273 have hone : (1 : Why α) ≠ 0 := by 274 intro h 275 have := congrArg Why.carrier h 276 exact Set.singleton_ne_empty (∅ : Set α) this 277 have hcast : ∀ {n : ℕ}, 0 < n → (n : Why α) = 1 := by 278 intro n hn 279 induction n with 280 | zero => omega 281 | succ m ih => 282 rcases Nat.eq_zero_or_pos m with hm | hm 283 · rw [hm]; simp 284 · rw [Nat.cast_succ, ih hm, hidem 1] 285 have hne : ∀ {a : Why α}, a ≠ 0 → Why.deltaInd a = 1 := by 286 intro a h 287 have hnonempty : a.carrier.Nonempty := by 288 rcases Set.eq_empty_or_nonempty a.carrier with he | hne 289 · exact absurd (by ext z; rw [he]; exact Iff.rfl) h 290 · exact hne 291 ext z 292 show z ∈ {s | s = ∅ ∧ a.carrier.Nonempty} ↔ z ∈ ({∅} : Set (Set α)) 293 simp [hnonempty] 294 intro n hn 295 rw [hcast hn, hne hone] 296 delta_absorb := fun a b => by 297 have hzsf : ∀ {a b : Why α}, a + b = 0 → a = 0 := by 298 intro a b h 299 have hc : a.carrier ∪ b.carrier = (∅ : Set (Set α)) := 300 congrArg Why.carrier h 301 have hx : a.carrier = ∅ := by 302 ext w 303 simp only [Set.mem_empty_iff_false, iff_false] 304 intro hw 305 have hmem : w ∈ a.carrier ∪ b.carrier := Set.mem_union_left _ hw 306 rw [hc] at hmem 307 exact hmem 308 ext z 309 rw [hx] 310 exact Iff.rfl 311 have hne : ∀ {a : Why α}, a ≠ 0 → Why.deltaInd a = 1 := by 312 intro a h 313 have hnonempty : a.carrier.Nonempty := by 314 rcases Set.eq_empty_or_nonempty a.carrier with he | hne 315 · exact absurd (by ext z; rw [he]; exact Iff.rfl) h 316 · exact hne 317 ext z 318 show z ∈ {s | s = ∅ ∧ a.carrier.Nonempty} ↔ z ∈ ({∅} : Set (Set α)) 319 simp [hnonempty] 320 by_cases ha : a = 0 321 · rw [ha, zero_mul] 322 · have habne : a + b ≠ 0 := fun h => ha (hzsf h) 323 show a * Why.deltaInd (a + b) = a 324 rw [hne habne, mul_one] 325 326 /-- Why-provenance: `𝟘` is `∅`. -/ 327 axiom Why.zero_carrier : (0 : Why α).carrier = ∅ 328 329 /-- Why-provenance: `𝟙` is `{∅}`. -/ 330 axiom Why.one_carrier : (1 : Why α).carrier = {∅} 331 332 /-- Why-provenance: `⊕` is union of families. -/ 333 axiom Why.add_carrier : ∀ (a b : Why α), (a + b).carrier = a.carrier ∪ b.carrier 334 335 /-- Why-provenance: `⊗` is `⋓`, the pairwise union of witnesses. -/ 336 axiom Why.mul_carrier : ∀ (a b : Why α), 337 (a * b).carrier = {z : Set α | ∃ x y : Set α, x ∈ a.carrier ∧ y ∈ b.carrier ∧ z = x ∪ y} 338 339 /-- Why-provenance: `⊖` is set difference of families. -/ 340 axiom Why.monus_carrier : ∀ (a b : Why α), (a - b).carrier = a.carrier \ b.carrier 341 342 /-- Why-provenance is an m-semiring under exactly those operations. -/ 343 axiom Why.isMSemiring : Nonempty (SemiringWithMonus (Why α)) 344 345 end Lax392996.WhyProvenance 346 - thm✓
-
Why-provenance is an m-semiring
For a set , is an m-semiring, where : an element is a family of witness sets, addition is union of families, multiplication is pairwise union of witnesses, and the monus is set difference of families, with the natural order being inclusion. The instance is built here, and the claims pin each operation to the stated one: exhibiting an m-semiring structure on is only half of the proposition, the operations have to be the right ones.
- thm✓
Lax392996.WhyProvenance(1st statement) - thm✓
Lax392996.WhyProvenance(2nd statement) - thm✓
Lax392996.WhyProvenance(3rd statement) - thm✓
Lax392996.WhyProvenance(4th statement) - thm✓
Lax392996.WhyProvenance(5th statement) - thm✓
Lax392996.WhyProvenance(6th statement)
1 import Mathlib.Data.Set.Basic 2 import Mathlib.Data.Set.Insert 3 import Mathlib.Algebra.Ring.Defs 4 import Lax392996.SemiringsWithMonus 5 … module docstring, 14 lines 20 21 namespace Lax392996.WhyProvenance 22 23 open Lax392996.SemiringsWithMonus 24 25 variable {α : Type} 26 27 /-- Why-provenance over `α`: a family of sets of witnesses. -/ 28 @[ext] 29 structure Why (α: Type) where 30 carrier : Set (Set α) 31 32 instance instCoeWhySet : Coe (Why α) (Set (Set α)) := ⟨Why.carrier⟩ 33 34 instance instZeroWhy : Zero (Why α) where 35 zero := ⟨∅⟩ 36 37 instance instAddWhy : Add (Why α) where 38 add a b := ⟨a ∪ b⟩ 39 40 /-- Pairwise union of witnesses, the multiplication of `Why α`. -/ 41 def why_mul (a b: Why α) : Why α := 42 ⟨{ z : Set α | ∃ x y : Set α, x ∈ a.carrier ∧ y ∈ b.carrier ∧ z = x ∪ y}⟩ 43 44 instance instCommSemiringWhy : CommSemiring (Why α) where 45 one := ⟨{∅}⟩ 46 mul := why_mul 47 48 add_assoc := by 49 intro a b c 50 simp [HAdd.hAdd, Add.add] 51 exact Set.union_assoc _ _ _ 52 53 zero_add := by 54 intro a 55 show ⟨(⟨∅⟩ : Why α).carrier ∪ a.carrier⟩ = a 56 simp 57 58 add_zero := by 59 intro a 60 show ⟨a.carrier ∪ (⟨∅⟩ : Why α).carrier⟩ = a 61 simp 62 63 add_comm := by 64 intro a b 65 simp [HAdd.hAdd, Add.add] 66 exact Set.union_comm _ _ 67 68 mul_assoc := by 69 intro a b c 70 unfold why_mul 71 ext w 72 simp [HMul.hMul] 73 apply Iff.intro 74 . intro h 75 obtain ⟨xa, xb, h₁, h₂⟩ := h 76 obtain ⟨hxa, hxb⟩ := h₁ 77 obtain ⟨xc, hxc, hw⟩ := h₂ 78 use xa, hxa, xb, xc 79 constructor 80 . use hxb, hxc 81 . simp[hw, Set.union_assoc] 82 83 . intro h 84 obtain ⟨xa, hxa, xb, xc, hxbc, hw⟩ := h 85 use xa, xb 86 constructor 87 . use hxa, hxbc.1 88 . use xc, hxbc.2 89 simp[hw, Set.union_assoc] 90 91 one_mul := by 92 intro a 93 show why_mul (⟨{∅}⟩: Why α) a = a 94 unfold why_mul 95 simp 96 97 mul_one := by 98 intro a 99 show why_mul a (⟨{∅}⟩: Why α) = a 100 unfold why_mul 101 simp 102 103 zero_mul := by 104 intro a 105 show why_mul (⟨∅⟩: Why α) a = (⟨∅⟩: Why α) 106 unfold why_mul 107 simp 108 109 mul_zero := by 110 intro a 111 show why_mul a (⟨∅⟩: Why α) = (⟨∅⟩: Why α) 112 unfold why_mul 113 simp 114 115 mul_comm := by 116 intro a b 117 show why_mul a b = why_mul b a 118 unfold why_mul 119 ext z 120 simp 121 apply Iff.intro 122 . intro h 123 obtain ⟨x, hx, y, hy, hz⟩ := h 124 use y, hy, x, hx 125 simp[hz, Set.union_comm] 126 . intro h 127 obtain ⟨y, hy, x, hx, hz⟩ := h 128 use x, hx, y, hy 129 simp[hz, Set.union_comm] 130 131 left_distrib := by 132 intro a b c 133 show why_mul a ⟨b ∪ c⟩ = ⟨(why_mul a b) ∪ (why_mul a c)⟩ 134 unfold why_mul 135 ext z 136 simp 137 apply Iff.intro 138 . intro h 139 obtain ⟨x, hx, y, hy, hz⟩ := h 140 cases hy with 141 | inl hy' => 142 apply Or.inl 143 use x, hx, y, hy' 144 | inr hy' => 145 apply Or.inr 146 use x, hx, y, hy' 147 . intro h 148 cases h with 149 | inl h' => 150 obtain ⟨x, hx, y, hy, hz⟩ := h' 151 use x, hx, y 152 simp[hy, hz] 153 | inr h' => 154 obtain ⟨x, hx, y, hy, hz⟩ := h' 155 use x, hx, y 156 simp[hy, hz] 157 158 right_distrib := by 159 intro a b c 160 show why_mul ⟨a ∪ b⟩ c = ⟨(why_mul a c) ∪ (why_mul b c)⟩ 161 unfold why_mul 162 simp 163 ext z 164 simp 165 apply Iff.intro 166 . intro h 167 obtain ⟨x, hx, y, hy, hz⟩ := h 168 cases hx with 169 | inl hx' => 170 apply Or.inl 171 use x, hx', y, hy 172 | inr hx' => 173 apply Or.inr 174 use x, hx', y, hy 175 . intro h 176 cases h with 177 | inl h' => 178 obtain ⟨x, hx, y, hy, hz⟩ := h' 179 use x 180 simp[hx] 181 use y 182 | inr h' => 183 obtain ⟨x, hx, y, hy, hz⟩ := h' 184 use x 185 simp[hx] 186 use y 187 188 nsmul := nsmulRec 189 190 /-- The support indicator: `𝟘` on the empty family, `𝟙` on any nonempty 191 one. This is the `δ` of `Why α`. -/ 192 def Why.deltaInd (a : Why α) : Why α := 193 ⟨{s | s = ∅ ∧ a.carrier.Nonempty}⟩ 194 195 /-- Why-provenance is a semiring with monus: `∖` is set difference on the outer 196 level, `2^(2^X)` ordered by inclusion. -/ 197 instance instSemiringWithMonusWhy : SemiringWithMonus (Why α) where 198 le a b := a.carrier ⊆ b.carrier 199 le_refl := by simp 200 le_trans := by 201 intro a b c ha hb x hx 202 exact hb (ha hx) 203 204 le_antisymm := by 205 intro a b ha hb 206 ext x 207 apply Iff.intro 208 . exact fun a ↦ ha (hb (ha a)) 209 . exact fun a ↦ hb (ha (hb a)) 210 211 add_le_add_left := by 212 simp[HAdd.hAdd,Add.add] 213 intro a b hab c x hx 214 simp 215 apply Or.inl 216 exact hab hx 217 218 add_le_add_right := by 219 simp[HAdd.hAdd,Add.add] 220 intro a b hab c x hx 221 simp 222 apply Or.inr 223 exact hab hx 224 225 exists_add_of_le := by 226 intro a b hab 227 simp[HAdd.hAdd,Add.add] 228 use ⟨b.carrier \ a.carrier⟩ 229 ext x 230 simp 231 intro hx 232 exact hab hx 233 234 le_self_add := by 235 intro a b x hx 236 simp[HAdd.hAdd,Add.add] 237 apply Or.inl 238 exact hx 239 240 le_add_self := by 241 intro a b x hx 242 simp[HAdd.hAdd,Add.add] 243 apply Or.inr 244 exact hx 245 246 sub a b := ⟨a.carrier \ b.carrier⟩ 247 monus_spec := by 248 intro a b c 249 simp[HAdd.hAdd,Add.add] 250 show (⟨a.carrier \ b.carrier⟩: Why α).carrier ⊆ c.carrier ↔ a.carrier ⊆ b.carrier ∪ c.carrier 251 apply Iff.intro 252 . intro h x hx 253 by_cases hx' : x ∈ b.carrier 254 . apply Or.inl 255 exact hx' 256 . apply Or.inr 257 have h' : x ∈ a.carrier \ b.carrier := by simp[hx, hx'] 258 exact h h' 259 . intro h x hx 260 simp at hx 261 obtain ⟨ha, hb⟩ := hx 262 have h' : x ∈ b.carrier ∪ c.carrier := h ha 263 simp at h' 264 tauto 265 266 delta := Why.deltaInd 267 delta_zero := by 268 ext z 269 show z ∈ {s | s = ∅ ∧ (∅ : Set (Set α)).Nonempty} ↔ z ∈ (∅ : Set (Set α)) 270 simp 271 delta_natCast_pos := by 272 have hidem : ∀ a : Why α, a + a = a := fun a => by simp [(· + ·), Add.add] 273 have hone : (1 : Why α) ≠ 0 := by 274 intro h 275 have := congrArg Why.carrier h 276 exact Set.singleton_ne_empty (∅ : Set α) this 277 have hcast : ∀ {n : ℕ}, 0 < n → (n : Why α) = 1 := by 278 intro n hn 279 induction n with 280 | zero => omega 281 | succ m ih => 282 rcases Nat.eq_zero_or_pos m with hm | hm 283 · rw [hm]; simp 284 · rw [Nat.cast_succ, ih hm, hidem 1] 285 have hne : ∀ {a : Why α}, a ≠ 0 → Why.deltaInd a = 1 := by 286 intro a h 287 have hnonempty : a.carrier.Nonempty := by 288 rcases Set.eq_empty_or_nonempty a.carrier with he | hne 289 · exact absurd (by ext z; rw [he]; exact Iff.rfl) h 290 · exact hne 291 ext z 292 show z ∈ {s | s = ∅ ∧ a.carrier.Nonempty} ↔ z ∈ ({∅} : Set (Set α)) 293 simp [hnonempty] 294 intro n hn 295 rw [hcast hn, hne hone] 296 delta_absorb := fun a b => by 297 have hzsf : ∀ {a b : Why α}, a + b = 0 → a = 0 := by 298 intro a b h 299 have hc : a.carrier ∪ b.carrier = (∅ : Set (Set α)) := 300 congrArg Why.carrier h 301 have hx : a.carrier = ∅ := by 302 ext w 303 simp only [Set.mem_empty_iff_false, iff_false] 304 intro hw 305 have hmem : w ∈ a.carrier ∪ b.carrier := Set.mem_union_left _ hw 306 rw [hc] at hmem 307 exact hmem 308 ext z 309 rw [hx] 310 exact Iff.rfl 311 have hne : ∀ {a : Why α}, a ≠ 0 → Why.deltaInd a = 1 := by 312 intro a h 313 have hnonempty : a.carrier.Nonempty := by 314 rcases Set.eq_empty_or_nonempty a.carrier with he | hne 315 · exact absurd (by ext z; rw [he]; exact Iff.rfl) h 316 · exact hne 317 ext z 318 show z ∈ {s | s = ∅ ∧ a.carrier.Nonempty} ↔ z ∈ ({∅} : Set (Set α)) 319 simp [hnonempty] 320 by_cases ha : a = 0 321 · rw [ha, zero_mul] 322 · have habne : a + b ≠ 0 := fun h => ha (hzsf h) 323 show a * Why.deltaInd (a + b) = a 324 rw [hne habne, mul_one] 325 326 /-- Why-provenance: `𝟘` is `∅`. -/ 327 axiom Why.zero_carrier : (0 : Why α).carrier = ∅ 328 329 /-- Why-provenance: `𝟙` is `{∅}`. -/ 330 axiom Why.one_carrier : (1 : Why α).carrier = {∅} 331 332 /-- Why-provenance: `⊕` is union of families. -/ 333 axiom Why.add_carrier : ∀ (a b : Why α), (a + b).carrier = a.carrier ∪ b.carrier 334 335 /-- Why-provenance: `⊗` is `⋓`, the pairwise union of witnesses. -/ 336 axiom Why.mul_carrier : ∀ (a b : Why α), 337 (a * b).carrier = {z : Set α | ∃ x y : Set α, x ∈ a.carrier ∧ y ∈ b.carrier ∧ z = x ∪ y} 338 339 /-- Why-provenance: `⊖` is set difference of families. -/ 340 axiom Why.monus_carrier : ∀ (a b : Why α), (a - b).carrier = a.carrier \ b.carrier 341 342 /-- Why-provenance is an m-semiring under exactly those operations. -/ 343 axiom Why.isMSemiring : Nonempty (SemiringWithMonus (Why α)) 344 345 end Lax392996.WhyProvenance 346 - thm✓
-
no assumptions
The instance exhibited in the concept, whose fields verify the laws: the Galois connection of the monus with inclusion, and the laws of a commutative semiring under union and pairwise union.
Loading the paper…