-
Notifications
You must be signed in to change notification settings - Fork 561
feat: hash map lemmas for filter, map and filterMap #7400
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: master
Are you sure you want to change the base?
Conversation
…into hashmap-filter-map
…into hashmap-filter-map
Mathlib CI status (docs):
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Lemmas LGTM except for the two remaining comments, so feel free to get started on the user-facing versions.
src/Std/Data/DHashMap/Lemmas.lean
Outdated
theorem distinct_keys [EquivBEq α] [LawfulHashable α] : | ||
m.keys.Pairwise (fun a b => (a == b) = false) := | ||
Raw₀.distinct_keys ⟨m.1, m.2.size_buckets_pos⟩ m.2 | ||
|
||
@[simp] | ||
theorem map_fst_toList_eq_keys [EquivBEq α] [LawfulHashable α] : | ||
m.1.toList.map Sigma.fst = m.1.keys := | ||
m.toList.map Sigma.fst = m.keys := |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I also changed these lines as they seemed to be nonsense for me with m.1.keys
…into hashmap-filter-map
…into hashmap-filter-map
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Looking very good, so this is mainly blocked on #7855.
src/Std/Data/HashSet/Lemmas.lean
Outdated
(m.filter f).get! k = ((m.get? k).filter f).get! := | ||
HashMap.getKey!_filter_key | ||
|
||
theorem getD_filter [EquivBEq α] [LawfulHashable α] [Inhabited α] |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Unnecessary Inhabited
instance?
@@ -1589,7 +1624,7 @@ theorem getElem_alter [EquivBEq α] [LawfulHashable α] {k k' : α} {f : Option | |||
f m[k]? |>.get h' | |||
else | |||
haveI h' : k' ∈ m := mem_alter_of_beq_eq_false (Bool.not_eq_true _ ▸ heq) |>.mp h | |||
m[k']'h' := | |||
m[(k')]'h' := |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Why is this suddenly needed?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Without the brackets Lean inteprets this term as containing the string ']' and because of that raises an error.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
A space helps alternatively as well.
src/Std/Data/HashMap/Lemmas.lean
Outdated
f (m.getKey k (mem_iff_isSome_getElem?.mpr (Option.isSome_of_eq_some h'))) x)).getD fallback := | ||
DHashMap.Const.getD_filter | ||
|
||
theorem getD_filter_of_getKey?_eq_some [EquivBEq α] [LawfulHashable α] [Inhabited β] |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Unneeded Inhabited
instance?
src/Std/Data/HashMap/Lemmas.lean
Outdated
|
||
theorem mem_of_mem_filter [EquivBEq α] [LawfulHashable α] | ||
{f : α → β → Bool} {k : α} : | ||
k ∈ (m.filter f) → k ∈ m := |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
k ∈ (m.filter f) → k ∈ m := | |
k ∈ m.filter f → k ∈ m := |
have h' := containsKey_of_mem h | ||
induction l with | ||
| nil => simp at h | ||
| cons hd tl ih => | ||
rw [containsKey_cons] at h' | ||
by_cases hd_x : hd.1 == x.1 | ||
· have : x = hd := by | ||
simp only [List.mem_cons] at h | ||
cases h with | ||
| inl h => exact h | ||
| inr h => | ||
rw [distinctKeys_cons_iff] at distinct | ||
rw [containsKey_eq_false_iff] at distinct | ||
have := And.right distinct | ||
specialize this x h | ||
simp [this] at hd_x | ||
simp only [← this] | ||
rw [getValue_cons] | ||
simp | ||
· rw [getValue_cons] | ||
rw [distinctKeys_cons_iff] at distinct | ||
simp only [hd_x, Bool.false_eq_true, ↓reduceDIte] | ||
simp only [Bool.not_eq_true] at hd_x | ||
have hd_x' : ¬ x = hd := by | ||
false_or_by_contra | ||
rename_i h' | ||
simp [h'] at hd_x | ||
simp only [List.mem_cons, hd_x', false_or] at h | ||
exact ih h (And.left distinct) (containsKey_of_mem h) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Shorter way:
have h' := containsKey_of_mem h | |
induction l with | |
| nil => simp at h | |
| cons hd tl ih => | |
rw [containsKey_cons] at h' | |
by_cases hd_x : hd.1 == x.1 | |
· have : x = hd := by | |
simp only [List.mem_cons] at h | |
cases h with | |
| inl h => exact h | |
| inr h => | |
rw [distinctKeys_cons_iff] at distinct | |
rw [containsKey_eq_false_iff] at distinct | |
have := And.right distinct | |
specialize this x h | |
simp [this] at hd_x | |
simp only [← this] | |
rw [getValue_cons] | |
simp | |
· rw [getValue_cons] | |
rw [distinctKeys_cons_iff] at distinct | |
simp only [hd_x, Bool.false_eq_true, ↓reduceDIte] | |
simp only [Bool.not_eq_true] at hd_x | |
have hd_x' : ¬ x = hd := by | |
false_or_by_contra | |
rename_i h' | |
simp [h'] at hd_x | |
simp only [List.mem_cons, hd_x', false_or] at h | |
exact ih h (And.left distinct) (containsKey_of_mem h) | |
induction h with | |
| head => rw [getValue_cons_of_beq]; simp | |
| @tail y l hmem ih => | |
obtain (h|h) := containsKey_cons_eq_true.1 h' | |
· have := containsKey_of_mem hmem ▸ containsKey_congr h ▸ distinct.containsKey_eq_false | |
simp at this | |
· rw [getValue_cons_of_false, ih distinct.tail] | |
refine Bool.not_eq_true _ ▸ (fun hb => ?_) | |
simp [← containsKey_congr hb, distinct.containsKey_eq_false] at h |
And similar below.
simp only [getKey, getKey?_eq_getEntry?, this] at h | ||
exact h | ||
|
||
theorem perm_filter_self_iff [BEq α] [LawfulBEq α] {f : (a : α) → β a → Bool} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This could be split into a general lemma and an associative-specific one:
theorem perm_filter_self_iff {f : α → Bool} {l : List α} :
(l.filter f).Perm l ↔ ∀ a ∈ l, f a = true := by
rw (occs := [1]) [← (List.filter_append_perm f _).congr_right,
← List.append_nil (List.filter _ _), List.perm_append_left_iff]
simp
theorem perm_filter_self_iff_forall_containsKey [BEq α] [LawfulBEq α] {f : (a : α) → β a → Bool}
{l : List ((a : α) × β a)} (hl : DistinctKeys l) :
List.Perm (l.filter fun p => f p.1 p.2) l ↔ ∀ (a : α) (h : containsKey a l),
(f a (getValueCast a l h)) = true := by
rw [perm_filter_self_iff]
constructor
· intro h a ha
exact h _ (getValueCast_mem ha)
· intro h a ha
exact getValueCast_of_mem ha hl ▸ h _ (containsKey_of_mem ha)
This PR adds lemmas for the
filter
,map
andfilterMap
functions of the hash map.