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: add list function and lemmas #987

Open
wants to merge 21 commits into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from 8 commits
Commits
Show all changes
21 commits
Select commit Hold shift + click to select a range
344bd60
feat: add lemmas about lists
chabulhwi Mar 18, 2024
87f4b94
feat: add more lemmas about lists
chabulhwi Oct 14, 2024
02599d9
style: avoid using `@` symbol
chabulhwi Oct 15, 2024
f39e00a
refactor: remove implicit instances of theorem
chabulhwi Oct 15, 2024
2d30498
refactor: put theorem in section
chabulhwi Oct 15, 2024
6b39d44
feat: add `List.commonPrefix` and its lemmas
chabulhwi Oct 15, 2024
ce38099
refactor: rename and restate theorem
chabulhwi Oct 15, 2024
6b7c0e4
chore: move definition to another file
chabulhwi Oct 15, 2024
ab8e65a
feat: add theorem `List.commonPrefix_comm`
chabulhwi Oct 16, 2024
9e0d971
style: avoid using `Decidable.em` directly
chabulhwi Oct 16, 2024
d257184
refactor: golf proofs
chabulhwi Oct 16, 2024
fa83dc7
Revert "refactor: golf proofs"
chabulhwi Oct 16, 2024
ffbd01f
Revert "style: avoid using `Decidable.em` directly"
chabulhwi Oct 16, 2024
49f306e
Revert "feat: add theorem `List.commonPrefix_comm`"
chabulhwi Oct 16, 2024
0e6bfd8
Revert "chore: move definition to another file"
chabulhwi Oct 16, 2024
10a0c0d
Revert "refactor: rename and restate theorem"
chabulhwi Oct 16, 2024
75ec590
Revert "feat: add `List.commonPrefix` and its lemmas"
chabulhwi Oct 16, 2024
f3a2b95
Revert "refactor: put theorem in section"
chabulhwi Oct 16, 2024
1d57ce4
Revert "refactor: remove implicit instances of theorem"
chabulhwi Oct 16, 2024
7c5ef34
chore: remove theorem
chabulhwi Oct 16, 2024
fa178b5
Merge branch 'main' into add-more-list-lemmas
fgdorais Oct 19, 2024
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
10 changes: 10 additions & 0 deletions Batteries/Data/List/Basic.lean
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,16 @@ namespace List

/-! ## New definitions -/

/-- Returns the longest common prefix of two lists. -/
def commonPrefix [DecidableEq α] : (l₁ l₂ : List α) → List α
| [], _ => []
| _, [] => []
| a₁::l₁, a₂::l₂ =>
if a₁ = a₂ then
a₁ :: (commonPrefix l₁ l₂)
else
[]

/--
Computes the "bag intersection" of `l₁` and `l₂`, that is,
the collection of elements of `l₁` which are also in `l₂`. As each element
Expand Down
86 changes: 86 additions & 0 deletions Batteries/Data/List/Lemmas.lean
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,15 @@ namespace List

@[deprecated (since := "2024-08-15")] alias isEmpty_iff_eq_nil := isEmpty_iff

/-! ### head and tail -/

theorem head_cons_tail : ∀ (l : List α) (hne : l ≠ []), l.head hne :: l.tail = l
| _::_, _ => rfl

theorem singleton_head_eq_self (l : List α) (hne : l ≠ []) (htl : l.tail = []) :
[l.head hne] = l := by
conv => rhs; rw [← head_cons_tail l hne, htl]

/-! ### next? -/

@[simp] theorem next?_nil : @next? α [] = none := rfl
Expand Down Expand Up @@ -482,6 +491,83 @@ theorem Sublist.erase_diff_erase_sublist {a : α} :

end Diff

/-! ### prefix, suffix, infix -/

theorem singleton_prefix_cons (a) : [a] <+: a :: l :=
(prefix_cons_inj a).mpr nil_prefix
fgdorais marked this conversation as resolved.
Show resolved Hide resolved

theorem ne_nil_of_not_prefix (h : ¬l₁ <+: l₂) : l₁ ≠ [] := by
intro heq
simp [heq, nil_prefix] at h
Comment on lines +499 to +501
Copy link
Collaborator

Choose a reason for hiding this comment

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

Suggested change
theorem ne_nil_of_not_prefix (h : ¬l₁ <+: l₂) : l₁ ≠ [] := by
intro heq
simp [heq, nil_prefix] at h
theorem ne_nil_of_not_prefix : ¬l₁ <+: l₂ → l₁ ≠ [] := by
apply mt; intro h; simp [h]


section

variable [DecidableEq α]

theorem commonPrefix_prefix_left (l₁ l₂ : List α) : commonPrefix l₁ l₂ <+: l₁ := by
match l₁, l₂ with
| [], _ => simp [commonPrefix]
| _::_, [] => simp [commonPrefix]
| a₁::l₁, a₂::l₂ =>
simp only [commonPrefix]
cases Decidable.em (a₁ = a₂)
· next h =>
simp only [h, ↓reduceIte, cons_prefix_cons, true_and]
apply commonPrefix_prefix_left
· next h =>
simp [h]
chabulhwi marked this conversation as resolved.
Show resolved Hide resolved

theorem commonPrefix_prefix_right (l₁ l₂ : List α) : commonPrefix l₁ l₂ <+: l₂ := by
match l₁, l₂ with
| [], _ => simp [commonPrefix]
| _::_, [] => simp [commonPrefix]
| a₁::l₁, a₂::l₂ =>
simp only [commonPrefix]
cases Decidable.em (a₁ = a₂)
· next h =>
simp only [h, ↓reduceIte, cons_prefix_cons, true_and]
apply commonPrefix_prefix_right
· next h =>
simp [h]
chabulhwi marked this conversation as resolved.
Show resolved Hide resolved

theorem commonPrefix_append_append (p l₁ l₂ : List α) :
commonPrefix (p ++ l₁) (p ++ l₂) = p ++ commonPrefix l₁ l₂ := by
match p with
| [] => rfl
| a::p => simpa [commonPrefix] using commonPrefix_append_append p l₁ l₂

theorem not_prefix_and_not_prefix_symm_iff {l₁ l₂ p t₁ t₂ : List α} (hp : commonPrefix l₁ l₂ = p)
(h₁ : l₁ = p ++ t₁) (h₂ : l₂ = p ++ t₂) : ¬l₁ <+: l₂ ∧ ¬l₂ <+: l₁ ↔ t₁ ≠ [] ∧ t₂ ≠ [] ∧
t₁.head? ≠ t₂.head? := by
constructor <;> intro h
· obtain ⟨a₁, l₁, rfl⟩ := l₁.exists_cons_of_ne_nil (ne_nil_of_not_prefix h.1)
obtain ⟨a₂, l₂, rfl⟩ := l₂.exists_cons_of_ne_nil (ne_nil_of_not_prefix h.2)
cases Decidable.em (a₁ = a₂)
· subst a₂
simp only [← hp, commonPrefix, ↓reduceIte, cons_append, cons.injEq, true_and] at h₁ h₂
simp only [cons_prefix_cons, true_and] at h
exact (not_prefix_and_not_prefix_symm_iff rfl h₁ h₂).mp h
· next hne =>
simp only [← hp, commonPrefix, hne, ↓reduceIte, nil_append] at h₁ h₂
simp [← h₁, ← h₂, hne]
· rw [h₁, h₂]
let ⟨ht₁, ht₂, hhd⟩ := h
obtain ⟨a₁, t₁, rfl⟩ := exists_cons_of_ne_nil ht₁
obtain ⟨a₂, t₂, rfl⟩ := exists_cons_of_ne_nil ht₂
simp only [head?_cons, ne_eq, Option.some.injEq] at hhd
rw [← ne_eq] at hhd
simp [prefix_append_right_inj, not_and_of_not_left _ hhd, not_and_of_not_left _ hhd.symm]
termination_by l₁.length
decreasing_by
rename_i _₀ _l₁ _₁ _₂ _₃ _₄ _₅ _₆ _₇ _r _₈ _₉ _₁₀ _₁₁ _₁₂ _₁₃ _₁₄ _₁₅ _₁₆ _₁₇ _₁₈ _hl₁ _₁₉ _₂₀ _₂₁
_₂₂ _₂₃ _₂₄ _₂₅ _₂₆ _₂₇
clear _₀ _₁ _₂ _₃ _₄ _₅ _₆ _₇ _r _₈ _₉ _₁₀ _₁₁ _₁₂ _₁₃ _₁₄ _₁₅ _₁₆ _₁₇ _₁₈ _₁₉ _₂₀ _₂₁ _₂₂ _₂₃ _₂₄
_₂₅ _₂₆ _₂₇
chabulhwi marked this conversation as resolved.
Show resolved Hide resolved
subst _l₁
simp

end

/-! ### drop -/

theorem disjoint_take_drop : ∀ {l : List α}, l.Nodup → m ≤ n → Disjoint (l.take m) (l.drop n)
Expand Down