Skip to content
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

feat: verify insertMany method for adding lists to HashMaps #6211

Draft
wants to merge 38 commits into
base: master
Choose a base branch
from

Conversation

monsterkrampe
Copy link
Contributor

This PR verifies the insertMany method on HashMaps for the special case of inserting lists.

@github-actions github-actions bot added the toolchain-available A toolchain is available for this PR, at leanprover/lean4-pr-releases:pr-release-NNNN label Nov 25, 2024
@leanprover-community-bot
Copy link
Collaborator

leanprover-community-bot commented Nov 25, 2024

Mathlib CI status (docs):

  • ❗ Batteries/Mathlib CI will not be attempted unless your PR branches off the nightly-with-mathlib branch. Try git rebase 935fcfb6ec84342163a86058856edcb1dca70ff4 --onto 884a9ea2ff70bb4d0c6da4a1c23ffc26c3a974ee. (2024-11-25 13:30:54)
  • ❗ Batteries/Mathlib CI will not be attempted unless your PR branches off the nightly-with-mathlib branch. Try git rebase 0a22f8fa6fef34a6798785785237c66cab173197 --onto 9a17919ef11c2dba824498229633b8333a0b53d9. (2024-11-26 15:53:38)
  • ❗ Batteries/Mathlib CI will not be attempted unless your PR branches off the nightly-with-mathlib branch. Try git rebase b378fe98a7877276b7dff70527b6c924e672c435 --onto 9a17919ef11c2dba824498229633b8333a0b53d9. (2024-11-27 15:47:35)
  • ❗ Batteries/Mathlib CI will not be attempted unless your PR branches off the nightly-with-mathlib branch. Try git rebase b378fe98a7877276b7dff70527b6c924e672c435 --onto 609346f5e03f3f2d559e7cc905f72e950c3ed8c4. (2024-11-28 08:49:25)
  • ❗ Batteries/Mathlib CI will not be attempted unless your PR branches off the nightly-with-mathlib branch. Try git rebase b378fe98a7877276b7dff70527b6c924e672c435 --onto 6d495586a1836da3e12efb4fbf9946bd9088ac5f. (2024-11-29 10:41:50)
  • ❗ Batteries/Mathlib CI will not be attempted unless your PR branches off the nightly-with-mathlib branch. Try git rebase b378fe98a7877276b7dff70527b6c924e672c435 --onto 86f303774a7fbf38406ae13bd4b66f2753643a45. (2024-11-30 15:42:21)
  • ❗ Batteries/Mathlib CI will not be attempted unless your PR branches off the nightly-with-mathlib branch. Try git rebase b378fe98a7877276b7dff70527b6c924e672c435 --onto 27df5e968a675780a7bcd105a19774c0c59295d8. (2024-12-01 19:35:29)
  • ❗ Batteries/Mathlib CI will not be attempted unless your PR branches off the nightly-with-mathlib branch. Try git rebase b378fe98a7877276b7dff70527b6c924e672c435 --onto 3c5e612dc54733cd707becb929457d2f9d8ca6fd. (2024-12-02 15:27:36)
  • ❗ Batteries/Mathlib CI will not be attempted unless your PR branches off the nightly-with-mathlib branch. Try git rebase d9d54c1f99363f42d1485f6b67f281a5985f684e --onto 3c5e612dc54733cd707becb929457d2f9d8ca6fd. (2024-12-02 22:28:30)
  • ❗ Batteries/Mathlib CI will not be attempted unless your PR branches off the nightly-with-mathlib branch. Try git rebase d9d54c1f99363f42d1485f6b67f281a5985f684e --onto cb600ed9b436e4290b819b0529f8454490bffeb6. (2024-12-03 16:10:17)

@TwoFX TwoFX self-assigned this Nov 26, 2024
@@ -285,6 +285,11 @@ but will later become a primitive operation.
⟨(Raw₀.insertMany ⟨m.1, m.2.size_buckets_pos⟩ l).1,
(Raw₀.insertMany ⟨m.1, m.2.size_buckets_pos⟩ l).2 _ Raw.WF.insert₀ m.2

@[inline, inherit_doc Raw.insertList] def insertList (m : DHashMap α β)
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I don't think we should expose an insertList function as part of the public API. Here is how I imagined this working:

  • you define insertListₘ (for example using the definition you have)
  • you prove a theorem insertMany_eq_insertListₘ in Model.lean which rewrites insertMany applied to a list directly to insertListₘ
  • in WF.lean, you prove theorems toListModel_insertListₘ, (wfImp_insertListₘ probably not needed) , toListModel_insertMany (which only applies to lists!)
  • all of the lemmas in Internal/RawLemmas.lean are stated in terms of insertMany but only apply if the input is a list.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I changed that. It remains open how to name the lemmas. I kept insertList for now in the name. Using just insertMany seems impractical in case someone verifies insertList for arrays, trees etc. insertMany_list seemed a bit long

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Long lemma names aren't necessarily a problem (we have IDE autocomplete ;)), so insertMany_list seems like the correct name to me.

src/Std/Data/DHashMap/Internal/RawLemmas.lean Outdated Show resolved Hide resolved
src/Std/Data/DHashMap/Internal/RawLemmas.lean Outdated Show resolved Hide resolved
src/Std/Data/DHashMap/Internal/RawLemmas.lean Outdated Show resolved Hide resolved
src/Std/Data/DHashMap/Internal/RawLemmas.lean Outdated Show resolved Hide resolved
src/Std/Data/DHashMap/Internal/List/Associative.lean Outdated Show resolved Hide resolved
src/Std/Data/DHashMap/Internal/List/Associative.lean Outdated Show resolved Hide resolved
src/Std/Data/DHashMap/Internal/RawLemmas.lean Outdated Show resolved Hide resolved
src/Std/Data/DHashMap/Internal/RawLemmas.lean Outdated Show resolved Hide resolved
src/Std/Data/DHashMap/Internal/RawLemmas.lean Outdated Show resolved Hide resolved
Copy link
Member

@TwoFX TwoFX left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Most of my comments focus on things like naming which make sense to get exactly right before copying the lemmas a bunch of times, because it is more fun to change a name two times compared to changing it eight times :)

src/Std/Data/DHashMap/Internal/Model.lean Outdated Show resolved Hide resolved
@@ -706,6 +706,29 @@ theorem wfImp_filter [BEq α] [Hashable α] [EquivBEq α] [LawfulHashable α] {m
rw [filter_eq_filterₘ]
exact wfImp_filterₘ h

/-! # `insertListₘ` -/
theorem wfImp_insertListₘ [BEq α] [Hashable α] [EquivBEq α][LawfulHashable α] {m : Raw₀ α β} {l : List ((a : α) × β a)} (h : Raw.WFImp m.1) : Raw.WFImp (m.insertListₘ l).1 := by
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This line is very long. If you have opened the Lean 4 workspace correctly, you should see a ruler at 100 columns. Please reformat your lines to stay within 100 columns.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I have WordWrapper activated in my vs code and then the ruler isn't moved in the wrapped line, but thats probably an issue only affecting very few users. I can keep an eye on that.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

If I'm understanding you correctly this only occurs if your editor window is less than 100 columns wide? If so, yes, I don't think many users do it that way :)

src/Std/Data/DHashMap/Internal/WF.lean Outdated Show resolved Hide resolved
@@ -706,6 +706,29 @@ theorem wfImp_filter [BEq α] [Hashable α] [EquivBEq α] [LawfulHashable α] {m
rw [filter_eq_filterₘ]
exact wfImp_filterₘ h

/-! # `insertListₘ` -/
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
/-! # `insertListₘ` -/
/-! # `insertListₘ` -/

(similar below)

apply ih (wfImp_insert h)
apply List.insertList_perm_of_perm_first
apply toListModel_insert h
apply (wfImp_insert h).distinct
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
apply (wfImp_insert h).distinct
apply (wfImp_insert h).distinct

src/Std/Data/DHashMap/Internal/RawLemmas.lean Outdated Show resolved Hide resolved
section
variable {β: Type v} (m: Raw₀ α (fun _ => β))

theorem get?_insertMany_list_not_mem_const [EquivBEq α] [LawfulHashable α]
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Should this not be called Const.get?_insertMany_of_contains_eq_false?

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This theorem appers twice for Const.get for general insertMany and for Const.get for Const.insertMany, which would collapse via this name. I introduced the const to differentiate between the normal get and this one, though I copied it also into the results in the Const namespace.

getKey (insertManyIfNewUnit m l).1 k' h' = k := by
simp_to_model using getKey_insertListIfNewUnit_mem

theorem getKey_insertManyIfNewUnit_list_mem_both [EquivBEq α] [LawfulHashable α]
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Let's avoid abbreviations as much as possible and derive theorem names as "mechanically" as possible. I would call this getKey_insertManyIfNewUnit_of_contains_of_contains. Note the of before hypotheses.

theorem getKey_insertManyIfNewUnit_list_mem_both [EquivBEq α] [LawfulHashable α]
{l : List α} {k : α}
{distinct : l.Pairwise (fun a b => (a == b) = false)}
{mem : l.contains k} {mem' : m.contains k = true} {h'} (h : m.1.WF):
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Here and in many other places, you should just write m.contains k instead of m.contains k = true when using a Prop statement.

getKeyD (insertManyIfNewUnit m l).1 k fallback = getKeyD m k fallback := by
simp_to_model using getKeyD_insertListIfNewUnit_mem_both

theorem insertManyIfNewUnit_list_length [EquivBEq α] [LawfulHashable α]
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We generally read function calls "outside-in", so the proper name here would be length_insertManyIfNewUnit.

src/Std/Data/DHashMap/Internal/RawLemmas.lean Outdated Show resolved Hide resolved
src/Std/Data/DHashMap/Internal/RawLemmas.lean Outdated Show resolved Hide resolved
src/Std/Data/DHashMap/Internal/RawLemmas.lean Outdated Show resolved Hide resolved
section
variable {β: Type v} (m: Raw₀ α (fun _ => β))

theorem get?_insertMany_list_of_contains_eq_false_const [EquivBEq α] [LawfulHashable α] (h : m.1.WF)
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Okay, I see the problem with naming these lemmas. I think the (admittedly slighly crazy) scheme we use for the naming here would be that the lemma lives in the namespace of the first thing that appears in the name and then other relevant namespaces are included in the theorem name as appropriate. So this lemma would be called Const.get?_insertMany_list_of_contains_eq_false and the lemma you're currently calling Const.get?_insertMany_list_of_contains_eq_false would be called Const.get?_constInsertMany_list_of_contains_eq_false. Luckily, it's unlikely that end users will need to interact with these lemmas directly.

src/Std/Data/DHashMap/Internal/WF.lean Outdated Show resolved Hide resolved
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
toolchain-available A toolchain is available for this PR, at leanprover/lean4-pr-releases:pr-release-NNNN
Projects
None yet
Development

Successfully merging this pull request may close these issues.

5 participants