Universal hashing
General
DefinitionCollision count#✓fully proved
For a finite family \(H\) of functions from a set \(\alpha\) to \(\{0, 1, \dots, m - 1\}\) and keys \(x, y \in \alpha\), the collision count of \(x\) and \(y\) in \(H\) is the number of functions \(h \in H\) with \(h(x) = h(y)\).
DefinitionUniversal hash family#✓fully proved
A finite family \(H\) of functions from a set \(\alpha\) to \(\{0, 1, \dots, m - 1\}\) is universal if \(m > 0\), \(H\) is nonempty, and for all distinct keys \(x \ne y\) in \(\alpha\) the number of functions \(h \in H\) with \(h(x) = h(y)\), multiplied by \(m\), is at most \(|H|\); that is, \(x\) and \(y\) collide under at most a \(1/m\) fraction of the members of \(H\).
Nonemptiness makes sense of choosing a member of \(H\) uniformly at random, the reading behind the bound.
public def IsUniversal (H : Finset (α → Fin m)) : Prop :=
0 < m ∧ H.Nonempty ∧ ∀ x y : α, x ≠ y → collisionCount H x y * m ≤ H.card
public def collisionCount (H : Finset (α → Fin m)) (x y : α) : Nat :=
(H.filter fun h => h x = h y).card
CSLibExt/Algorithms/Lean/DataStructures/UniversalHashing.lean:74
Uses 1 · Used by 1
DefinitionIndexed universal hash family#✓fully proved
Let \(s\) be a finite set of indices from a type \(\iota\), and let \(h\) assign to each index \(i \in \iota\) a function \(h_i\) from a set \(\alpha\) to \(\{0, 1, \dots, m - 1\}\). The family \(h\) is universal on \(s\) if \(m > 0\), \(s\) is nonempty, and for all distinct keys \(x \ne y\) in \(\alpha\) the number of indices \(i \in s\) with \(h_i(x) = h_i(y)\), multiplied by \(m\), is at most \(|s|\).
Each index is counted separately, even when two indices give the same function; this is the form in which the classical counting arguments, including the one for the mod-prime family, are carried out. Nonemptiness is required because there is no uniform random choice from an empty family.
public def IsUniversalOn {ι : Type v} (s : Finset ι) (h : ι → α → Fin m) : Prop :=
0 < m ∧ s.Nonempty ∧
∀ x y : α, x ≠ y → (s.filter fun i => h i x = h i y).card * m ≤ s.card
Used by 2
TheoremCollision count is at most the family size#✓fully proved
For every finite family \(H\) of functions from a set \(\alpha\) to \(\{0, 1, \dots, m - 1\}\) and all keys \(x, y \in \alpha\), the number of functions \(h \in H\) with \(h(x) = h(y)\) is at most \(|H|\).
public theorem collisionCount_le_card (H : Finset (α → Fin m)) (x y : α) :
collisionCount H x y ≤ H.card
public def collisionCount (H : Finset (α → Fin m)) (x y : α) : Nat :=
(H.filter fun h => h x = h y).card
CSLibExt/Algorithms/Lean/DataStructures/UniversalHashing.lean:74
Uses 1
TheoremA key collides with itself under the whole family#✓fully proved
For every finite family \(H\) of functions from a set \(\alpha\) to \(\{0, 1, \dots, m - 1\}\) and every key \(x \in \alpha\), the collision count of \(x\) with itself in \(H\) equals \(|H|\): \(x\) collides with itself under every function in \(H\).
@[simp]
public theorem collisionCount_self (H : Finset (α → Fin m)) (x : α) :
collisionCount H x x = H.card
public def collisionCount (H : Finset (α → Fin m)) (x y : α) : Nat :=
(H.filter fun h => h x = h y).card
CSLibExt/Algorithms/Lean/DataStructures/UniversalHashing.lean:74
Uses 1
TheoremThe empty hash family is not universal#✓fully proved
For every type of keys \(\alpha\) and every natural number \(m\), the empty family of functions \(\alpha \to \{0, \dots, m - 1\}\) is not universal: universality includes nonemptiness, since its meaning is a bound on the collision probability for a uniformly chosen member.
public theorem not_isUniversal_empty : ¬ IsUniversal (∅ : Finset (α → Fin m))
public def IsUniversal (H : Finset (α → Fin m)) : Prop :=
0 < m ∧ H.Nonempty ∧ ∀ x y : α, x ≠ y → collisionCount H x y * m ≤ H.card
CSLibExt/Algorithms/Lean/DataStructures/UniversalHashing.lean:83
Uses 2
TheoremThe empty indexed family is not universal#✓fully proved
For every index type \(\iota\), every type of keys \(\alpha\), every natural number \(m\) and every family \((h_i)_{i \in \iota}\) of functions \(h_i \colon \alpha \to \{0, \dots, m - 1\}\), the family is not universal over the empty index set: indexed universality includes nonemptiness of the index set, since there is no uniform random choice from an empty family.
public theorem not_isUniversalOn_empty {ι : Type v} (h : ι → α → Fin m) :
¬ IsUniversalOn (∅ : Finset ι) h
public def IsUniversalOn {ι : Type v} (s : Finset ι) (h : ι → α → Fin m) : Prop :=
0 < m ∧ s.Nonempty ∧
∀ x y : α, x ≠ y → (s.filter fun i => h i x = h i y).card * m ≤ s.card
CSLibExt/Algorithms/Lean/DataStructures/UniversalHashing.lean:93
Uses 1
TheoremThe empty family satisfies the collision bound#✓fully proved
For every natural number \(m\) and all distinct keys \(x \ne y\) in a set \(\alpha\), the collision count of \(x\) and \(y\) in the empty family of functions from \(\alpha\) to \(\{0, 1, \dots, m - 1\}\), multiplied by \(m\), is at most the size of the empty family, which is \(0\).
This is the collision bound of universality without its other conditions; universality also requires the family to be nonempty and \(m > 0\), so the empty family is not universal.
public theorem isUniversal_bound_empty :
∀ x y : α, x ≠ y →
collisionCount (∅ : Finset (α → Fin m)) x y * m ≤
(∅ : Finset (α → Fin m)).card
public def collisionCount (H : Finset (α → Fin m)) (x y : α) : Nat :=
(H.filter fun h => h x = h y).card
CSLibExt/Algorithms/Lean/DataStructures/UniversalHashing.lean:74
Uses 1
Mod Prime
DefinitionMod-prime hash function#✓fully proved
For natural numbers \(p\) and \(m\) with \(m > 0\) and elements \(a, b\) of \(\mathbb{Z}/p\mathbb{Z}\), the mod-prime hash function \(h_{a,b} \colon \mathbb{Z}/p\mathbb{Z} \to \{0, \dots, m - 1\}\) is \(h_{a,b}(x) = \operatorname{val}(ax + b) \bmod m\), where \(ax + b\) is computed in \(\mathbb{Z}/p\mathbb{Z}\) and \(\operatorname{val}(z)\) is the canonical natural-number representative of \(z\) (the residue in \(\{0, \dots, p - 1\}\) when \(p > 0\), and \(|z|\) when \(p = 0\)). This is the function \(h_{a,b}(x) = ((ax + b) \bmod p) \bmod m\) of CLRS Section 11.3.3.
public def modPrimeHash (p m : Nat) (hm : 0 < m) (a b x : ZMod p) : Fin m :=
⟨(a * x + b).val % m, Nat.mod_lt _ hm⟩
AbbreviationMod-prime index set#✓fully proved
For a natural number \(p\), the index set of the mod-prime family is the set of pairs \((a, b)\) with \(a, b \in \mathbb{Z}/p\mathbb{Z}\) and \(a \neq 0\).
Used by 12
DefinitionIndexed mod-prime family#✓fully proved
For natural numbers \(p\) and \(m\) with \(m > 0\), the indexed mod-prime family assigns to each index \((a, b)\), with \(a, b \in \mathbb{Z}/p\mathbb{Z}\) and \(a \neq 0\), the mod-prime hash function \(h_{a,b} \colon \mathbb{Z}/p\mathbb{Z} \to \{0, \dots, m - 1\}\).
public def modPrimeHashes (p m : Nat) (hm : 0 < m) (ab : ModPrimeIndex p) :
ZMod p → Fin m :=
fun x => modPrimeHash p m hm ab.1.1 ab.2 x
public abbrev ModPrimeIndex (p : Nat) : Type :=
{ a : ZMod p // a ≠ 0 } × ZMod p
CSLibExt/Algorithms/Lean/DataStructures/UniversalHashing.lean:145
public def modPrimeHash (p m : Nat) (hm : 0 < m) (a b x : ZMod p) : Fin m :=
⟨(a * x + b).val % m, Nat.mod_lt _ hm⟩
CSLibExt/Algorithms/Lean/DataStructures/UniversalHashing.lean:141
Uses 2 · Used by 4
DefinitionMod-prime family of distinct functions#✓fully proved
For \(p > 0\) and \(m > 0\), the mod-prime family is the finite set of all functions \(h_{a,b}\) from \(\mathbb{Z}/p\mathbb{Z}\) to \(\{0, 1, \dots, m - 1\}\) with \(a, b \in \mathbb{Z}/p\mathbb{Z}\) and \(a \ne 0\), where \(h_{a,b}\) is the mod-prime hash function with index \((a, b)\).
Universality is proved for the indexed family of mod-prime hash functions, matching the \(p(p - 1)\) count of indices in CLRS; this set of distinct functions can be smaller, since distinct index pairs may give the same function after the final reduction modulo \(m\).
public def modPrimeFamily (p m : Nat) [NeZero p] (hm : 0 < m) :
Finset (ZMod p → Fin m) :=
Finset.univ.image (modPrimeHashes p m hm)
public def modPrimeHashes (p m : Nat) (hm : 0 < m) (ab : ModPrimeIndex p) :
ZMod p → Fin m :=
fun x => modPrimeHash p m hm ab.1.1 ab.2 x
CSLibExt/Algorithms/Lean/DataStructures/UniversalHashing.lean:149
Uses 2 · Used by 1
TheoremValue of the mod-prime hash#✓fully proved
For natural numbers \(p\) and \(m\) with \(m > 0\) and elements \(a, b, x\) of \(\mathbb{Z}/p\mathbb{Z}\), the mod-prime hash value \(h_{a,b}(x) \in \{0, \dots, m - 1\}\), read as a natural number, equals \(\operatorname{val}(ax + b) \bmod m\). Here \(ax + b\) is computed in \(\mathbb{Z}/p\mathbb{Z}\), and \(\operatorname{val}(z)\) is the canonical natural-number representative of \(z\): the residue in \(\{0, \dots, p - 1\}\) when \(p > 0\), and \(|z|\) when \(p = 0\).
@[simp]
public theorem modPrimeHash_val (p m : Nat) (hm : 0 < m) (a b x : ZMod p) :
(modPrimeHash p m hm a b x).val = (a * x + b).val % m
public def modPrimeHash (p m : Nat) (hm : 0 < m) (a b x : ZMod p) : Fin m :=
⟨(a * x + b).val % m, Nat.mod_lt _ hm⟩
CSLibExt/Algorithms/Lean/DataStructures/UniversalHashing.lean:141
Uses 1
TheoremCollisions of a mod-prime hash function#✓fully proved
Let \(p\) be a natural number, \(m > 0\) and \(a, b \in \mathbb{Z}/p\mathbb{Z}\), and write \(\operatorname{val}(z)\) for the canonical natural-number representative of \(z \in \mathbb{Z}/p\mathbb{Z}\) (for \(p = 0\), where \(\mathbb{Z}/0\mathbb{Z} = \mathbb{Z}\), its absolute value), so that the mod-prime hash function is \(h_{a,b}(x) = \operatorname{val}(ax + b) \bmod m\). For all keys \(x, y \in \mathbb{Z}/p\mathbb{Z}\), we have \(h_{a,b}(x) = h_{a,b}(y)\) exactly when \(\operatorname{val}(ax + b) \bmod m = \operatorname{val}(ay + b) \bmod m\).
public theorem modPrimeHash_eq_iff (p m : Nat) (hm : 0 < m) (a b x y : ZMod p) :
modPrimeHash p m hm a b x = modPrimeHash p m hm a b y ↔
(a * x + b).val % m = (a * y + b).val % m
public def modPrimeHash (p m : Nat) (hm : 0 < m) (a b x : ZMod p) : Fin m :=
⟨(a * x + b).val % m, Nat.mod_lt _ hm⟩
CSLibExt/Algorithms/Lean/DataStructures/UniversalHashing.lean:141
Uses 1 · Used by 1
DefinitionThe pair map of the mod-prime family#✓fully proved
Let \(p\) be a natural number and fix two keys \(x, y \in \mathbb{Z}/p\mathbb{Z}\). The pair map at \(x\) and \(y\) sends an index \((a, b)\) of the mod-prime family, that is, \(a, b \in \mathbb{Z}/p\mathbb{Z}\) with \(a \ne 0\), to the pair \((ax + b, ay + b) \in (\mathbb{Z}/p\mathbb{Z})^2\) of inner hash values at \(x\) and \(y\).
This is the map of the CLRS counting argument for the mod-prime family.
public def pairMap {p : Nat} (x y : ZMod p) (ab : ModPrimeIndex p) : ZMod p × ZMod p :=
(ab.1.1 * x + ab.2, ab.1.1 * y + ab.2)
public abbrev ModPrimeIndex (p : Nat) : Type :=
{ a : ZMod p // a ≠ 0 } × ZMod p
CSLibExt/Algorithms/Lean/DataStructures/UniversalHashing.lean:145
TheoremEvaluating the pair map#✓fully proved
Let \(p\) be a natural number, let \(x, y \in \mathbb{Z}/p\mathbb{Z}\), and let \((a, b)\) be an index of the mod-prime family, so that \(a, b \in \mathbb{Z}/p\mathbb{Z}\) and \(a \ne 0\). Then the pair map at \(x\) and \(y\) sends \((a, b)\) to \((ax + b, ay + b)\).
@[simp]
public theorem pairMap_apply {p : Nat} (x y : ZMod p) (ab : ModPrimeIndex p) :
pairMap x y ab = (ab.1.1 * x + ab.2, ab.1.1 * y + ab.2)
public abbrev ModPrimeIndex (p : Nat) : Type :=
{ a : ZMod p // a ≠ 0 } × ZMod p
CSLibExt/Algorithms/Lean/DataStructures/UniversalHashing.lean:145
public def pairMap {p : Nat} (x y : ZMod p) (ab : ModPrimeIndex p) : ZMod p × ZMod p :=
(ab.1.1 * x + ab.2, ab.1.1 * y + ab.2)
CSLibExt/Algorithms/Lean/DataStructures/UniversalHashing.lean:179
Uses 2
TheoremThe two values of the pair map differ#✓fully proved
Let \(p\) be a prime and let \(x \ne y\) be keys in the field \(\mathbb{Z}/p\mathbb{Z}\). For every index \((a, b)\) of the mod-prime family, that is, \(a, b \in \mathbb{Z}/p\mathbb{Z}\) with \(a \ne 0\), we have \(ax + b \ne ay + b\).
Indeed, the difference \((ax + b) - (ay + b) = a(x - y)\) is a product of two nonzero factors.
public theorem pairMap_fst_ne_snd {p : Nat} [Fact p.Prime] {x y : ZMod p}
(hxy : x ≠ y) (ab : ModPrimeIndex p) :
(pairMap x y ab).1 ≠ (pairMap x y ab).2
public abbrev ModPrimeIndex (p : Nat) : Type :=
{ a : ZMod p // a ≠ 0 } × ZMod p
CSLibExt/Algorithms/Lean/DataStructures/UniversalHashing.lean:145
public def pairMap {p : Nat} (x y : ZMod p) (ab : ModPrimeIndex p) : ZMod p × ZMod p :=
(ab.1.1 * x + ab.2, ab.1.1 * y + ab.2)
CSLibExt/Algorithms/Lean/DataStructures/UniversalHashing.lean:179
Uses 2 · Used by 2
DefinitionPair bijection of the CLRS counting argument#✓fully proved
Let \(p\) be a prime and let \(x \neq y\) be elements of the field \(\mathbb{Z}/p\mathbb{Z}\). The pair bijection for \(x, y\) is the bijection from the indices \((a, b)\), with \(a, b \in \mathbb{Z}/p\mathbb{Z}\) and \(a \neq 0\), to the ordered pairs \((r, s)\) of elements of \(\mathbb{Z}/p\mathbb{Z}\) with \(r \neq s\) that sends \((a, b)\) to the pair map value \((ax + b, ay + b)\). Its inverse solves the linear system \(ax + b = r\), \(ay + b = s\): it sends \((r, s)\) to \((a, b)\) with \(a = (r - s)/(x - y)\) and \(b = r - ax\).
Cslib.Algorithms.Lean.UniversalHashing.pairEquiv · 31 lines
public def pairEquiv {p : Nat} [Fact p.Prime] {x y : ZMod p} (hxy : x ≠ y) :
ModPrimeIndex p ≃ { rs : ZMod p × ZMod p // rs.1 ≠ rs.2 } where
toFun ab := ⟨pairMap x y ab, pairMap_fst_ne_snd hxy ab⟩
invFun rs :=
(⟨(rs.1.1 - rs.1.2) / (x - y),
div_ne_zero (sub_ne_zero.mpr rs.2) (sub_ne_zero.mpr hxy)⟩,
rs.1.1 - ((rs.1.1 - rs.1.2) / (x - y)) * x)
left_inv := by
intro ab
obtain ⟨⟨a, ha⟩, b⟩ := ab
have hxy' : (x - y) ≠ 0 := sub_ne_zero.mpr hxy
have haeq : ((a * x + b) - (a * y + b)) / (x - y) = a := by
have hnum : (a * x + b) - (a * y + b) = a * (x - y) := by ring
rw [hnum]
exact mul_div_cancel_right₀ a hxy'
apply Prod.ext
· exact Subtype.ext haeq
· show (a * x + b) - (((a * x + b) - (a * y + b)) / (x - y)) * x = b
rw [haeq]
ring
right_inv := by
intro rs
obtain ⟨⟨r, s⟩, hrs⟩ := rs
have hxy' : (x - y) ≠ 0 := sub_ne_zero.mpr hxy
have hkey : ((r - s) / (x - y)) * (x - y) = r - s := div_mul_cancel₀ _ hxy'
apply Subtype.ext
apply Prod.ext
· show ((r - s) / (x - y)) * x + (r - ((r - s) / (x - y)) * x) = r
ring
· show ((r - s) / (x - y)) * y + (r - ((r - s) / (x - y)) * x) = s
linear_combination -hkey
public abbrev ModPrimeIndex (p : Nat) : Type :=
{ a : ZMod p // a ≠ 0 } × ZMod p
CSLibExt/Algorithms/Lean/DataStructures/UniversalHashing.lean:145
public def pairMap {p : Nat} (x y : ZMod p) (ab : ModPrimeIndex p) : ZMod p × ZMod p :=
(ab.1.1 * x + ab.2, ab.1.1 * y + ab.2)
CSLibExt/Algorithms/Lean/DataStructures/UniversalHashing.lean:179
public theorem pairMap_fst_ne_snd {p : Nat} [Fact p.Prime] {x y : ZMod p}
(hxy : x ≠ y) (ab : ModPrimeIndex p) :
(pairMap x y ab).1 ≠ (pairMap x y ab).2
CSLibExt/Algorithms/Lean/DataStructures/UniversalHashing.lean:192
Uses 3 · Used by 3
TheoremThe pair bijection is given by the pair map#✓fully proved
Let \(p\) be a prime and let \(x \neq y\) be elements of \(\mathbb{Z}/p\mathbb{Z}\). For every index \((a, b)\) with \(a, b \in \mathbb{Z}/p\mathbb{Z}\) and \(a \neq 0\), the image of \((a, b)\) under the pair bijection for \(x, y\), viewed as an element of \(\mathbb{Z}/p\mathbb{Z} \times \mathbb{Z}/p\mathbb{Z}\), is the value of the pair map at \((a, b)\), namely \((ax + b, ay + b)\).
@[simp]
public theorem pairEquiv_apply_fst {p : Nat} [Fact p.Prime] {x y : ZMod p}
(hxy : x ≠ y) (ab : ModPrimeIndex p) :
(pairEquiv hxy ab).1 = pairMap x y ab
public abbrev ModPrimeIndex (p : Nat) : Type :=
{ a : ZMod p // a ≠ 0 } × ZMod p
CSLibExt/Algorithms/Lean/DataStructures/UniversalHashing.lean:145
public def pairEquiv {p : Nat} [Fact p.Prime] {x y : ZMod p} (hxy : x ≠ y) :
ModPrimeIndex p ≃ { rs : ZMod p × ZMod p // rs.1 ≠ rs.2 } where
toFun ab := ⟨pairMap x y ab, pairMap_fst_ne_snd hxy ab⟩
invFun rs :=
(⟨(rs.1.1 - rs.1.2) / (x - y),
div_ne_zero (sub_ne_zero.mpr rs.2) (sub_ne_zero.mpr hxy)⟩,
rs.1.1 - ((rs.1.1 - rs.1.2) / (x - y)) * x)
left_inv := by
intro ab
obtain ⟨⟨a, ha⟩, b⟩ := ab
have hxy' : (x - y) ≠ 0 := sub_ne_zero.mpr hxy
have haeq : ((a * x + b) - (a * y + b)) / (x - y) = a := by
⋯
CSLibExt/Algorithms/Lean/DataStructures/UniversalHashing.lean:210
public def pairMap {p : Nat} (x y : ZMod p) (ab : ModPrimeIndex p) : ZMod p × ZMod p :=
(ab.1.1 * x + ab.2, ab.1.1 * y + ab.2)
CSLibExt/Algorithms/Lean/DataStructures/UniversalHashing.lean:179
Uses 3 · Used by 1
TheoremThe pair map is injective#✓fully proved
Let \(p\) be a prime and let \(x \ne y\) be keys in \(\mathbb{Z}/p\mathbb{Z}\). Then the pair map at \(x\) and \(y\), which sends an index \((a, b)\) of the mod-prime family (so \(a, b \in \mathbb{Z}/p\mathbb{Z}\) and \(a \ne 0\)) to \((ax + b, ay + b)\), is injective.
public theorem pairMap_injective {p : Nat} [Fact p.Prime] {x y : ZMod p}
(hxy : x ≠ y) : Function.Injective (pairMap x y)
public def pairMap {p : Nat} (x y : ZMod p) (ab : ModPrimeIndex p) : ZMod p × ZMod p :=
(ab.1.1 * x + ab.2, ab.1.1 * y + ab.2)
CSLibExt/Algorithms/Lean/DataStructures/UniversalHashing.lean:179
Uses 3
TheoremCollision bound for the mod-prime hash functions#✓fully proved
Let \(p\) be a prime and \(m > 0\), and for \(a, b \in \mathbb{Z}/p\mathbb{Z}\) with \(a \ne 0\) let \(h_{a,b}(x) = ((ax + b) \bmod p) \bmod m\) be the mod-prime hash function. For distinct keys \(x \ne y\) in \(\mathbb{Z}/p\mathbb{Z}\), the number of index pairs \((a, b)\) with \(a \ne 0\) and \(h_{a,b}(x) = h_{a,b}(y)\), multiplied by \(m\), is at most \(p(p - 1)\), the total number of index pairs.
This is the counting step of CLRS Theorem 11.5. The bijection \((a, b) \mapsto (ax + b, ay + b)\) identifies the colliding index pairs with the pairs \((r, s)\) of distinct residues modulo \(p\) whose representatives in \(\{0, \dots, p - 1\}\) are congruent modulo \(m\).
public theorem modPrime_collision_mul_le {p m : Nat} [Fact p.Prime]
(hm : 0 < m) {x y : ZMod p} (hxy : x ≠ y) :
(Finset.univ.filter fun ab : ModPrimeIndex p =>
modPrimeHashes p m hm ab x = modPrimeHashes p m hm ab y).card * m ≤
p * (p - 1)
public abbrev ModPrimeIndex (p : Nat) : Type :=
{ a : ZMod p // a ≠ 0 } × ZMod p
CSLibExt/Algorithms/Lean/DataStructures/UniversalHashing.lean:145
public def modPrimeHashes (p m : Nat) (hm : 0 < m) (ab : ModPrimeIndex p) :
ZMod p → Fin m :=
fun x => modPrimeHash p m hm ab.1.1 ab.2 x
CSLibExt/Algorithms/Lean/DataStructures/UniversalHashing.lean:149
Uses 8 · Used by 1
TheoremNumber of mod-prime indices#✓fully proved
For every positive natural number \(p\), the set of pairs \((a, b)\) of elements of \(\mathbb{Z}/p\mathbb{Z}\) with \(a \neq 0\) has exactly \(p(p - 1)\) elements.
public theorem modPrimeIndex_card {p : Nat} [NeZero p] :
Fintype.card (ModPrimeIndex p) = p * (p - 1)
public abbrev ModPrimeIndex (p : Nat) : Type :=
{ a : ZMod p // a ≠ 0 } × ZMod p
CSLibExt/Algorithms/Lean/DataStructures/UniversalHashing.lean:145
Uses 1 · Used by 1
TheoremUniversality of the mod-prime family#✓fully proved
Let \(p\) be a prime and \(m\) a positive natural number. The indexed mod-prime family, whose member at the index \((a, b)\), with \(a, b \in \mathbb{Z}/p\mathbb{Z}\) and \(a \neq 0\), is the mod-prime hash function \(h_{a,b}\), is universal over the set of all such indices: this set is nonempty, and for all distinct keys \(x \neq y\) in \(\mathbb{Z}/p\mathbb{Z}\), the number of indices \((a, b)\) with \(h_{a,b}(x) = h_{a,b}(y)\), multiplied by \(m\), is at most the number of indices. This is CLRS Theorem 11.5.
A uniformly random index therefore collides on any two distinct keys with probability at most \(1/m\).
public theorem modPrime_isUniversalOn {p m : Nat} [Fact p.Prime]
(hm : 0 < m) :
IsUniversalOn Finset.univ (modPrimeHashes p m hm)
public def IsUniversalOn {ι : Type v} (s : Finset ι) (h : ι → α → Fin m) : Prop :=
0 < m ∧ s.Nonempty ∧
∀ x y : α, x ≠ y → (s.filter fun i => h i x = h i y).card * m ≤ s.card
CSLibExt/Algorithms/Lean/DataStructures/UniversalHashing.lean:93
public def modPrimeHashes (p m : Nat) (hm : 0 < m) (ab : ModPrimeIndex p) :
ZMod p → Fin m :=
fun x => modPrimeHash p m hm ab.1.1 ab.2 x
CSLibExt/Algorithms/Lean/DataStructures/UniversalHashing.lean:149
Uses 5
TheoremMembers of the mod-prime family#✓fully proved
Let \(p > 0\) and \(m > 0\). A function \(h\) from \(\mathbb{Z}/p\mathbb{Z}\) to \(\{0, 1, \dots, m - 1\}\) belongs to the mod-prime family of distinct functions exactly when \(h = h_{a,b}\) for some index \((a, b)\) with \(a, b \in \mathbb{Z}/p\mathbb{Z}\) and \(a \ne 0\), where \(h_{a,b}\) is the mod-prime hash function with index \((a, b)\).
@[simp]
public theorem mem_modPrimeFamily {p m : Nat} [NeZero p] (hm : 0 < m)
(h : ZMod p → Fin m) :
h ∈ modPrimeFamily p m hm ↔ ∃ ab : ModPrimeIndex p, modPrimeHashes p m hm ab = h
public def modPrimeFamily (p m : Nat) [NeZero p] (hm : 0 < m) :
Finset (ZMod p → Fin m) :=
Finset.univ.image (modPrimeHashes p m hm)
CSLibExt/Algorithms/Lean/DataStructures/UniversalHashing.lean:159
public abbrev ModPrimeIndex (p : Nat) : Type :=
{ a : ZMod p // a ≠ 0 } × ZMod p
CSLibExt/Algorithms/Lean/DataStructures/UniversalHashing.lean:145
public def modPrimeHashes (p m : Nat) (hm : 0 < m) (ab : ModPrimeIndex p) :
ZMod p → Fin m :=
fun x => modPrimeHash p m hm ab.1.1 ab.2 x
CSLibExt/Algorithms/Lean/DataStructures/UniversalHashing.lean:149
Uses 3
Loading dependency explorer…
The dependency explorer needs JavaScript and its graph data.