l3lab/ntp-mathlib huggingface dataset:
@[simp]
theorem mem_erase {a a' : α} {s : Finmap β} : a' ∈ erase a s ↔ a' ≠ a ∧ a' ∈ s :=
  induction_on s fun s => by 

Proof state:
α : Type u
β : α → Type v
inst✝ : DecidableEq α
a a' : α
s✝ : Finmap β
s : AList β
⊢ a' ∈ erase a ⟦s⟧ ↔ a' ≠ a ∧ a' ∈ ⟦s⟧

Next tactic:
simp
theorem not_mem_erase_self {a : α} {s : Finmap β} : ¬a ∈ erase a s := by
  

Proof state:
α : Type u
β : α → Type v
inst✝ : DecidableEq α
a : α
s : Finmap β
⊢ a ∉ erase a s

Next tactic:
rw [mem_erase, not_and_or, not_not]
theorem not_mem_erase_self {a : α} {s : Finmap β} : ¬a ∈ erase a s := by
  rw [mem_erase, not_and_or, not_not]
  

Proof state:
α : Type u
β : α → Type v
inst✝ : DecidableEq α
a : α
s : Finmap β
⊢ a = a ∨ a ∉ s

Next tactic:
left
theorem not_mem_erase_self {a : α} {s : Finmap β} : ¬a ∈ erase a s := by
  rw [mem_erase, not_and_or, not_not]
  left
  

Proof state:
case h
α : Type u
β : α → Type v
inst✝ : DecidableEq α
a : α
s : Finmap β
⊢ a = a

Next tactic:
rfl
theorem erase_erase {a a' : α} {s : Finmap β} : erase a (erase a' s) = erase a' (erase a s) :=
  induction_on s fun s => ext (by 

Proof state:
α : Type u
β : α → Type v
inst✝ : DecidableEq α
a a' : α
s✝ : Finmap β
s : AList β
⊢ (erase a (erase a' ⟦s⟧)).entries = (erase a' (erase a ⟦s⟧)).entries

Next tactic:
simp only [AList.erase_erase, erase_toFinmap]
@[simp]
theorem insert_toFinmap (a : α) (b : β a) (s : AList β) :
    insert a b (AList.toFinmap s) = AList.toFinmap (s.insert a b) := by
  

Proof state:
α : Type u
β : α → Type v
inst✝ : DecidableEq α
a : α
b : β a
s : AList β
⊢ insert a b ⟦s⟧ = ⟦AList.insert a b s⟧

Next tactic:
simp [insert]
theorem insert_entries_of_neg {a : α} {b : β a} {s : Finmap β} :
    a ∉ s → (insert a b s).entries = ⟨a, b⟩ ::ₘ s.entries :=
  induction_on s fun s h => by
    -- Porting note: `-insert_entries` required
    

Proof state:
α : Type u
β : α → Type v
inst✝ : DecidableEq α
a : α
b : β a
s✝ : Finmap β
s : AList β
h : a ∉ ⟦s⟧
⊢ (insert a b ⟦s⟧).entries = { fst := a, snd := b } ::ₘ ⟦s⟧.entries

Next tactic:
simp [AList.insert_entries_of_neg (mt mem_toFinmap.1 h), -insert_entries]
@[simp]
theorem lookup_insert {a} {b : β a} (s : Finmap β) : lookup a (insert a b s) = some b :=
  induction_on s fun s => by 

Proof state:
α : Type u
β : α → Type v
inst✝ : DecidableEq α
a : α
b : β a
s✝ : Finmap β
s : AList β
⊢ lookup a (insert a b ⟦s⟧) = some b

Next tactic:
simp only [insert_toFinmap, lookup_toFinmap, AList.lookup_insert]
@[simp]
theorem lookup_insert_of_ne {a a'} {b : β a} (s : Finmap β) (h : a' ≠ a) :
    lookup a' (insert a b s) = lookup a' s :=
  induction_on s fun s => by 

Proof state:
α : Type u
β : α → Type v
inst✝ : DecidableEq α
a a' : α
b : β a
s✝ : Finmap β
h : a' ≠ a
s : AList β
⊢ lookup a' (insert a b ⟦s⟧) = lookup a' ⟦s⟧

Next tactic:
simp only [insert_toFinmap, lookup_toFinmap, lookup_insert_ne h]
@[simp]
theorem insert_insert {a} {b b' : β a} (s : Finmap β) :
    (s.insert a b).insert a b' = s.insert a b' :=
  induction_on s fun s => by 

Proof state:
α : Type u
β : α → Type v
inst✝ : DecidableEq α
a : α
b b' : β a
s✝ : Finmap β
s : AList β
⊢ insert a b' (insert a b ⟦s⟧) = insert a b' ⟦s⟧

Next tactic:
simp only [insert_toFinmap, AList.insert_insert]
theorem insert_insert_of_ne {a a'} {b : β a} {b' : β a'} (s : Finmap β) (h : a ≠ a') :
    (s.insert a b).insert a' b' = (s.insert a' b').insert a b :=
  induction_on s fun s => by
    

Proof state:
α : Type u
β : α → Type v
inst✝ : DecidableEq α
a a' : α
b : β a
b' : β a'
s✝ : Finmap β
h : a ≠ a'
s : AList β
⊢ insert a' b' (insert a b ⟦s⟧) = insert a b (insert a' b' ⟦s⟧)

Next tactic:
simp only [insert_toFinmap, AList.toFinmap_eq, AList.insert_insert_of_ne _ h]
theorem mem_list_toFinmap (a : α) (xs : List (Sigma β)) :
    a ∈ xs.toFinmap ↔ ∃ b : β a, Sigma.mk a b ∈ xs := by
  -- Porting note: golfed
  

Proof state:
α : Type u
β : α → Type v
inst✝ : DecidableEq α
a : α
xs : List (Sigma β)
⊢ a ∈ List.toFinmap xs ↔ ∃ b, { fst := a, snd := b } ∈ xs

Next tactic:
induction' xs with x xs
theorem mem_list_toFinmap (a : α) (xs : List (Sigma β)) :
    a ∈ xs.toFinmap ↔ ∃ b : β a, Sigma.mk a b ∈ xs := by
  -- Porting note: golfed
  induction' xs with x xs
  · 

Proof state:
case nil
α : Type u
β : α → Type v
inst✝ : DecidableEq α
a : α
⊢ a ∈ List.toFinmap [] ↔ ∃ b, { fst := a, snd := b } ∈ []

Next tactic:
simp only [toFinmap_nil, not_mem_empty, find?, not_mem_nil, exists_false]
theorem mem_list_toFinmap (a : α) (xs : List (Sigma β)) :
    a ∈ xs.toFinmap ↔ ∃ b : β a, Sigma.mk a b ∈ xs := by
  -- Porting note: golfed
  induction' xs with x xs
  · simp only [toFinmap_nil, not_mem_empty, find?, not_mem_nil, exists_false]
  

Proof state:
case cons
α : Type u
β : α → Type v
inst✝ : DecidableEq α
a : α
x : Sigma β
xs : List (Sigma β)
tail_ih✝ : a ∈ List.toFinmap xs ↔ ∃ b, { fst := a, snd := b } ∈ xs
⊢ a ∈ List.toFinmap (x :: xs) ↔ ∃ b, { fst := a, snd := b } ∈ x :: xs

Next tactic:
cases' x with fst_i snd_i
theorem mem_list_toFinmap (a : α) (xs : List (Sigma β)) :
    a ∈ xs.toFinmap ↔ ∃ b : β a, Sigma.mk a b ∈ xs := by
  -- Porting note: golfed
  induction' xs with x xs
  · simp only [toFinmap_nil, not_mem_empty, find?, not_mem_nil, exists_false]
  cases' x with fst_i snd_i
  -- Porting note: `Sigma.mk.inj_iff` required because `simp` behaves differently
  

Proof state:
case cons.mk
α : Type u
β : α → Type v
inst✝ : DecidableEq α
a : α
xs : List (Sigma β)
tail_ih✝ : a ∈ List.toFinmap xs ↔ ∃ b, { fst := a, snd := b } ∈ xs
fst_i : α
snd_i : β fst_i
⊢ a ∈ List.toFinmap ({ fst := fst_i, snd := snd_i } :: xs) ↔
    ∃ b, { fst := a, snd := b } ∈ { fst := fst_i, snd := snd_i } :: xs

Next tactic:
simp only [toFinmap_cons, *, exists_or, mem_cons, mem_insert, exists_and_left, Sigma.mk.inj_iff]
theorem mem_list_toFinmap (a : α) (xs : List (Sigma β)) :
    a ∈ xs.toFinmap ↔ ∃ b : β a, Sigma.mk a b ∈ xs := by
  -- Porting note: golfed
  induction' xs with x xs
  · simp only [toFinmap_nil, not_mem_empty, find?, not_mem_nil, exists_false]
  cases' x with fst_i snd_i
  -- Porting note: `Sigma.mk.inj_iff` required because `simp` behaves differently
  simp only [toFinmap_cons, *, exists_or, mem_cons, mem_insert, exists_and_left, Sigma.mk.inj_iff]
  

Proof state:
case cons.mk
α : Type u
β : α → Type v
inst✝ : DecidableEq α
a : α
xs : List (Sigma β)
tail_ih✝ : a ∈ List.toFinmap xs ↔ ∃ b, { fst := a, snd := b } ∈ xs
fst_i : α
snd_i : β fst_i
⊢ (a = fst_i ∨ ∃ b, { fst := a, snd := b } ∈ xs) ↔ (a = fst_i ∧ ∃ x, HEq x snd_i) ∨ ∃ x, { fst := a, snd := x } ∈ xs

Next tactic:
refine (or_congr_left <| and_iff_left_of_imp ?_).symm
theorem mem_list_toFinmap (a : α) (xs : List (Sigma β)) :
    a ∈ xs.toFinmap ↔ ∃ b : β a, Sigma.mk a b ∈ xs := by
  -- Porting note: golfed
  induction' xs with x xs
  · simp only [toFinmap_nil, not_mem_empty, find?, not_mem_nil, exists_false]
  cases' x with fst_i snd_i
  -- Porting note: `Sigma.mk.inj_iff` required because `simp` behaves differently
  simp only [toFinmap_cons, *, exists_or, mem_cons, mem_insert, exists_and_left, Sigma.mk.inj_iff]
  refine (or_congr_left <| and_iff_left_of_imp ?_).symm
  

Proof state:
case cons.mk
α : Type u
β : α → Type v
inst✝ : DecidableEq α
a : α
xs : List (Sigma β)
tail_ih✝ : a ∈ List.toFinmap xs ↔ ∃ b, { fst := a, snd := b } ∈ xs
fst_i : α
snd_i : β fst_i
⊢ a = fst_i → ∃ x, HEq x snd_i

Next tactic:
rintro rfl
theorem mem_list_toFinmap (a : α) (xs : List (Sigma β)) :
    a ∈ xs.toFinmap ↔ ∃ b : β a, Sigma.mk a b ∈ xs := by
  -- Porting note: golfed
  induction' xs with x xs
  · simp only [toFinmap_nil, not_mem_empty, find?, not_mem_nil, exists_false]
  cases' x with fst_i snd_i
  -- Porting note: `Sigma.mk.inj_iff` required because `simp` behaves differently
  simp only [toFinmap_cons, *, exists_or, mem_cons, mem_insert, exists_and_left, Sigma.mk.inj_iff]
  refine (or_congr_left <| and_iff_left_of_imp ?_).symm
  rintro rfl
  

Proof state:
case cons.mk
α : Type u
β : α → Type v
inst✝ : DecidableEq α
a : α
xs : List (Sigma β)
tail_ih✝ : a ∈ List.toFinmap xs ↔ ∃ b, { fst := a, snd := b } ∈ xs
snd_i : β a
⊢ ∃ x, HEq x snd_i

Next tactic:
simp only [exists_eq, heq_iff_eq]
@[simp]
theorem insert_singleton_eq {a : α} {b b' : β a} : insert a b (singleton a b') = singleton a b := by
  

Proof state:
α : Type u
β : α → Type v
inst✝ : DecidableEq α
a : α
b b' : β a
⊢ insert a b (singleton a b') = singleton a b

Next tactic:
simp only [singleton, Finmap.insert_toFinmap, AList.insert_singleton_eq]
/-- Erase a key from the map, and return the corresponding value, if found. -/
def extract (a : α) (s : Finmap β) : Option (β a) × Finmap β :=
  (liftOn s fun t => Prod.map id AList.toFinmap (AList.extract a t)) fun s₁ s₂ p => by
    

Proof state:
α : Type u
β : α → Type v
inst✝ : DecidableEq α
a : α
s : Finmap β
s₁ s₂ : AList β
p : s₁.entries ~ s₂.entries
⊢ Prod.map id AList.toFinmap (AList.extract a s₁) = Prod.map id AList.toFinmap (AList.extract a s₂)

Next tactic:
simp [perm_lookup p, toFinmap_eq, perm_erase p]
@[simp]
theorem extract_eq_lookup_erase (a : α) (s : Finmap β) : extract a s = (lookup a s, erase a s) :=
  induction_on s fun s => by 

Proof state:
α : Type u
β : α → Type v
inst✝ : DecidableEq α
a : α
s✝ : Finmap β
s : AList β
⊢ extract a ⟦s⟧ = (lookup a ⟦s⟧, erase a ⟦s⟧)

Next tactic:
simp [extract]
@[simp]
theorem union_toFinmap (s₁ s₂ : AList β) : (toFinmap s₁) ∪ (toFinmap s₂) = toFinmap (s₁ ∪ s₂) := by
  

Proof state:
α : Type u
β : α → Type v
inst✝ : DecidableEq α
s₁ s₂ : AList β
⊢ ⟦s₁⟧ ∪ ⟦s₂⟧ = ⟦s₁ ∪ s₂⟧

Next tactic:
simp [(· ∪ ·), union]
theorem keys_union {s₁ s₂ : Finmap β} : (s₁ ∪ s₂).keys = s₁.keys ∪ s₂.keys :=
  induction_on₂ s₁ s₂ fun s₁ s₂ => Finset.ext <| by 

Proof state:
α : Type u
β : α → Type v
inst✝ : DecidableEq α
s₁✝ s₂✝ : Finmap β
s₁ s₂ : AList β
⊢ ∀ (a : α), a ∈ keys (⟦s₁⟧ ∪ ⟦s₂⟧) ↔ a ∈ keys ⟦s₁⟧ ∪ keys ⟦s₂⟧

Next tactic:
simp [keys]
theorem lookup_union_left_of_not_in {a} {s₁ s₂ : Finmap β} (h : a ∉ s₂) :
    lookup a (s₁ ∪ s₂) = lookup a s₁ := by
  

Proof state:
α : Type u
β : α → Type v
inst✝ : DecidableEq α
a : α
s₁ s₂ : Finmap β
h : a ∉ s₂
⊢ lookup a (s₁ ∪ s₂) = lookup a s₁

Next tactic:
by_cases h' : a ∈ s₁
theorem lookup_union_left_of_not_in {a} {s₁ s₂ : Finmap β} (h : a ∉ s₂) :
    lookup a (s₁ ∪ s₂) = lookup a s₁ := by
  by_cases h' : a ∈ s₁
  · 

Proof state:
case pos
α : Type u
β : α → Type v
inst✝ : DecidableEq α
a : α
s₁ s₂ : Finmap β
h : a ∉ s₂
h' : a ∈ s₁
⊢ lookup a (s₁ ∪ s₂) = lookup a s₁

Next tactic:
rw [lookup_union_left h']
theorem lookup_union_left_of_not_in {a} {s₁ s₂ : Finmap β} (h : a ∉ s₂) :
    lookup a (s₁ ∪ s₂) = lookup a s₁ := by
  by_cases h' : a ∈ s₁
  · rw [lookup_union_left h']
  · 

Proof state:
case neg
α : Type u
β : α → Type v
inst✝ : DecidableEq α
a : α
s₁ s₂ : Finmap β
h : a ∉ s₂
h' : a ∉ s₁
⊢ lookup a (s₁ ∪ s₂) = lookup a s₁

Next tactic:
rw [lookup_union_right h', lookup_eq_none.mpr h, lookup_eq_none.mpr h']
theorem insert_union {a} {b : β a} {s₁ s₂ : Finmap β} : insert a b (s₁ ∪ s₂) = insert a b s₁ ∪ s₂ :=
  induction_on₂ s₁ s₂ fun a₁ a₂ => by 

Proof state:
α : Type u
β : α → Type v
inst✝ : DecidableEq α
a : α
b : β a
s₁ s₂ : Finmap β
a₁ a₂ : AList β
⊢ insert a b (⟦a₁⟧ ∪ ⟦a₂⟧) = insert a b ⟦a₁⟧ ∪ ⟦a₂⟧

Next tactic:
simp [AList.insert_union]
theorem union_assoc {s₁ s₂ s₃ : Finmap β} : s₁ ∪ s₂ ∪ s₃ = s₁ ∪ (s₂ ∪ s₃) :=
  induction_on₃ s₁ s₂ s₃ fun s₁ s₂ s₃ => by
    

Proof state:
α : Type u
β : α → Type v
inst✝ : DecidableEq α
s₁✝ s₂✝ s₃✝ : Finmap β
s₁ s₂ s₃ : AList β
⊢ ⟦s₁⟧ ∪ ⟦s₂⟧ ∪ ⟦s₃⟧ = ⟦s₁⟧ ∪ (⟦s₂⟧ ∪ ⟦s₃⟧)

Next tactic:
simp only [AList.toFinmap_eq, union_toFinmap, AList.union_assoc]
@[simp]
theorem empty_union {s₁ : Finmap β} : ∅ ∪ s₁ = s₁ :=
  induction_on s₁ fun s₁ => by
    

Proof state:
α : Type u
β : α → Type v
inst✝ : DecidableEq α
s₁✝ : Finmap β
s₁ : AList β
⊢ ∅ ∪ ⟦s₁⟧ = ⟦s₁⟧

Next tactic:
rw [← empty_toFinmap]
@[simp]
theorem empty_union {s₁ : Finmap β} : ∅ ∪ s₁ = s₁ :=
  induction_on s₁ fun s₁ => by
    rw [← empty_toFinmap]
    

Proof state:
α : Type u
β : α → Type v
inst✝ : DecidableEq α
s₁✝ : Finmap β
s₁ : AList β
⊢ ⟦∅⟧ ∪ ⟦s₁⟧ = ⟦s₁⟧

Next tactic:
simp [-empty_toFinmap, AList.toFinmap_eq, union_toFinmap, AList.union_assoc]
@[simp]
theorem union_empty {s₁ : Finmap β} : s₁ ∪ ∅ = s₁ :=
  induction_on s₁ fun s₁ => by
    

Proof state:
α : Type u
β : α → Type v
inst✝ : DecidableEq α
s₁✝ : Finmap β
s₁ : AList β
⊢ ⟦s₁⟧ ∪ ∅ = ⟦s₁⟧

Next tactic:
rw [← empty_toFinmap]
@[simp]
theorem union_empty {s₁ : Finmap β} : s₁ ∪ ∅ = s₁ :=
  induction_on s₁ fun s₁ => by
    rw [← empty_toFinmap]
    

Proof state:
α : Type u
β : α → Type v
inst✝ : DecidableEq α
s₁✝ : Finmap β
s₁ : AList β
⊢ ⟦s₁⟧ ∪ ⟦∅⟧ = ⟦s₁⟧

Next tactic:
simp [-empty_toFinmap, AList.toFinmap_eq, union_toFinmap, AList.union_assoc]
theorem erase_union_singleton (a : α) (b : β a) (s : Finmap β) (h : s.lookup a = some b) :
    s.erase a ∪ singleton a b = s :=
  ext_lookup fun x => by
    

Proof state:
α : Type u
β : α → Type v
inst✝ : DecidableEq α
a : α
b : β a
s : Finmap β
h : lookup a s = some b
x : α
⊢ lookup x (erase a s ∪ singleton a b) = lookup x s

Next tactic:
by_cases h' : x = a
theorem erase_union_singleton (a : α) (b : β a) (s : Finmap β) (h : s.lookup a = some b) :
    s.erase a ∪ singleton a b = s :=
  ext_lookup fun x => by
    by_cases h' : x = a
    · 

Proof state:
case pos
α : Type u
β : α → Type v
inst✝ : DecidableEq α
a : α
b : β a
s : Finmap β
h : lookup a s = some b
x : α
h' : x = a
⊢ lookup x (erase a s ∪ singleton a b) = lookup x s

Next tactic:
subst a
theorem erase_union_singleton (a : α) (b : β a) (s : Finmap β) (h : s.lookup a = some b) :
    s.erase a ∪ singleton a b = s :=
  ext_lookup fun x => by
    by_cases h' : x = a
    · subst a
      

Proof state:
case pos
α : Type u
β : α → Type v
inst✝ : DecidableEq α
s : Finmap β
x : α
b : β x
h : lookup x s = some b
⊢ lookup x (erase x s ∪ singleton x b) = lookup x s

Next tactic:
rw [lookup_union_right not_mem_erase_self, lookup_singleton_eq, h]
theorem erase_union_singleton (a : α) (b : β a) (s : Finmap β) (h : s.lookup a = some b) :
    s.erase a ∪ singleton a b = s :=
  ext_lookup fun x => by
    by_cases h' : x = a
    · subst a
      rw [lookup_union_right not_mem_erase_self, lookup_singleton_eq, h]
    · 

Proof state:
case neg
α : Type u
β : α → Type v
inst✝ : DecidableEq α
a : α
b : β a
s : Finmap β
h : lookup a s = some b
x : α
h' : ¬x = a
⊢ lookup x (erase a s ∪ singleton a b) = lookup x s

Next tactic:
have : x ∉ singleton a b := by rwa [mem_singleton]
theorem erase_union_singleton (a : α) (b : β a) (s : Finmap β) (h : s.lookup a = some b) :
    s.erase a ∪ singleton a b = s :=
  ext_lookup fun x => by
    by_cases h' : x = a
    · subst a
      rw [lookup_union_right not_mem_erase_self, lookup_singleton_eq, h]
    · have : x ∉ singleton a b := by 

Proof state:
α : Type u
β : α → Type v
inst✝ : DecidableEq α
a : α
b : β a
s : Finmap β
h : lookup a s = some b
x : α
h' : ¬x = a
⊢ x ∉ singleton a b

Next tactic:
rwa [mem_singleton]
theorem erase_union_singleton (a : α) (b : β a) (s : Finmap β) (h : s.lookup a = some b) :
    s.erase a ∪ singleton a b = s :=
  ext_lookup fun x => by
    by_cases h' : x = a
    · subst a
      rw [lookup_union_right not_mem_erase_self, lookup_singleton_eq, h]
    · have : x ∉ singleton a b := by rwa [mem_singleton]
      

Proof state:
case neg
α : Type u
β : α → Type v
inst✝ : DecidableEq α
a : α
b : β a
s : Finmap β
h : lookup a s = some b
x : α
h' : ¬x = a
this : x ∉ singleton a b
⊢ lookup x (erase a s ∪ singleton a b) = lookup x s

Next tactic:
rw [lookup_union_left_of_not_in this, lookup_erase_ne h']
instance : DecidableRel (@Disjoint α β) := fun x y => by 

Proof state:
α : Type u
β : α → Type v
inst✝ : DecidableEq α
x y : Finmap β
⊢ Decidable (Disjoint x y)

Next tactic:
dsimp only [Disjoint]
instance : DecidableRel (@Disjoint α β) := fun x y => by dsimp only [Disjoint]; 

Proof state:
α : Type u
β : α → Type v
inst✝ : DecidableEq α
x y : Finmap β
⊢ Decidable (∀ x_1 ∈ x, x_1 ∉ y)

Next tactic:
infer_instance
theorem disjoint_union_left (x y z : Finmap β) : Disjoint (x ∪ y) z ↔ Disjoint x z ∧ Disjoint y z :=
  by 

Proof state:
α : Type u
β : α → Type v
inst✝ : DecidableEq α
x y z : Finmap β
⊢ Disjoint (x ∪ y) z ↔ Disjoint x z ∧ Disjoint y z

Next tactic:
simp [Disjoint, Finmap.mem_union, or_imp, forall_and]
theorem disjoint_union_right (x y z : Finmap β) :
    Disjoint x (y ∪ z) ↔ Disjoint x y ∧ Disjoint x z := by
  

Proof state:
α : Type u
β : α → Type v
inst✝ : DecidableEq α
x y z : Finmap β
⊢ Disjoint x (y ∪ z) ↔ Disjoint x y ∧ Disjoint x z

Next tactic:
rw [Disjoint.symm_iff, disjoint_union_left, Disjoint.symm_iff _ x, Disjoint.symm_iff _ x]
theorem union_comm_of_disjoint {s₁ s₂ : Finmap β} : Disjoint s₁ s₂ → s₁ ∪ s₂ = s₂ ∪ s₁ :=
  induction_on₂ s₁ s₂ fun s₁ s₂ => by
    

Proof state:
α : Type u
β : α → Type v
inst✝ : DecidableEq α
s₁✝ s₂✝ : Finmap β
s₁ s₂ : AList β
⊢ Disjoint ⟦s₁⟧ ⟦s₂⟧ → ⟦s₁⟧ ∪ ⟦s₂⟧ = ⟦s₂⟧ ∪ ⟦s₁⟧

Next tactic:
intro h
theorem union_comm_of_disjoint {s₁ s₂ : Finmap β} : Disjoint s₁ s₂ → s₁ ∪ s₂ = s₂ ∪ s₁ :=
  induction_on₂ s₁ s₂ fun s₁ s₂ => by
    intro h
    

Proof state:
α : Type u
β : α → Type v
inst✝ : DecidableEq α
s₁✝ s₂✝ : Finmap β
s₁ s₂ : AList β
h : Disjoint ⟦s₁⟧ ⟦s₂⟧
⊢ ⟦s₁⟧ ∪ ⟦s₂⟧ = ⟦s₂⟧ ∪ ⟦s₁⟧

Next tactic:
simp only [AList.toFinmap_eq, union_toFinmap, AList.union_comm_of_disjoint h]
theorem union_cancel {s₁ s₂ s₃ : Finmap β} (h : Disjoint s₁ s₃) (h' : Disjoint s₂ s₃) :
    s₁ ∪ s₃ = s₂ ∪ s₃ ↔ s₁ = s₂ :=
  ⟨fun h'' => by
    

Proof state:
α : Type u
β : α → Type v
inst✝ : DecidableEq α
s₁ s₂ s₃ : Finmap β
h : Disjoint s₁ s₃
h' : Disjoint s₂ s₃
h'' : s₁ ∪ s₃ = s₂ ∪ s₃
⊢ s₁ = s₂

Next tactic:
apply ext_lookup
theorem union_cancel {s₁ s₂ s₃ : Finmap β} (h : Disjoint s₁ s₃) (h' : Disjoint s₂ s₃) :
    s₁ ∪ s₃ = s₂ ∪ s₃ ↔ s₁ = s₂ :=
  ⟨fun h'' => by
    apply ext_lookup
    

Proof state:
case a
α : Type u
β : α → Type v
inst✝ : DecidableEq α
s₁ s₂ s₃ : Finmap β
h : Disjoint s₁ s₃
h' : Disjoint s₂ s₃
h'' : s₁ ∪ s₃ = s₂ ∪ s₃
⊢ ∀ (x : α), lookup x s₁ = lookup x s₂

Next tactic:
intro x
theorem union_cancel {s₁ s₂ s₃ : Finmap β} (h : Disjoint s₁ s₃) (h' : Disjoint s₂ s₃) :
    s₁ ∪ s₃ = s₂ ∪ s₃ ↔ s₁ = s₂ :=
  ⟨fun h'' => by
    apply ext_lookup
    intro x
    

Proof state:
case a
α : Type u
β : α → Type v
inst✝ : DecidableEq α
s₁ s₂ s₃ : Finmap β
h : Disjoint s₁ s₃
h' : Disjoint s₂ s₃
h'' : s₁ ∪ s₃ = s₂ ∪ s₃
x : α
⊢ lookup x s₁ = lookup x s₂

Next tactic:
have : (s₁ ∪ s₃).lookup x = (s₂ ∪ s₃).lookup x := h'' ▸ rfl
theorem union_cancel {s₁ s₂ s₃ : Finmap β} (h : Disjoint s₁ s₃) (h' : Disjoint s₂ s₃) :
    s₁ ∪ s₃ = s₂ ∪ s₃ ↔ s₁ = s₂ :=
  ⟨fun h'' => by
    apply ext_lookup
    intro x
    have : (s₁ ∪ s₃).lookup x = (s₂ ∪ s₃).lookup x := h'' ▸ rfl
    

Proof state:
case a
α : Type u
β : α → Type v
inst✝ : DecidableEq α
s₁ s₂ s₃ : Finmap β
h : Disjoint s₁ s₃
h' : Disjoint s₂ s₃
h'' : s₁ ∪ s₃ = s₂ ∪ s₃
x : α
this : lookup x (s₁ ∪ s₃) = lookup x (s₂ ∪ s₃)
⊢ lookup x s₁ = lookup x s₂

Next tactic:
by_cases hs₁ : x ∈ s₁
theorem union_cancel {s₁ s₂ s₃ : Finmap β} (h : Disjoint s₁ s₃) (h' : Disjoint s₂ s₃) :
    s₁ ∪ s₃ = s₂ ∪ s₃ ↔ s₁ = s₂ :=
  ⟨fun h'' => by
    apply ext_lookup
    intro x
    have : (s₁ ∪ s₃).lookup x = (s₂ ∪ s₃).lookup x := h'' ▸ rfl
    by_cases hs₁ : x ∈ s₁
    · 

Proof state:
case pos
α : Type u
β : α → Type v
inst✝ : DecidableEq α
s₁ s₂ s₃ : Finmap β
h : Disjoint s₁ s₃
h' : Disjoint s₂ s₃
h'' : s₁ ∪ s₃ = s₂ ∪ s₃
x : α
this : lookup x (s₁ ∪ s₃) = lookup x (s₂ ∪ s₃)
hs₁ : x ∈ s₁
⊢ lookup x s₁ = lookup x s₂

Next tactic:
rwa [lookup_union_left hs₁, lookup_union_left_of_not_in (h _ hs₁)] at this
theorem union_cancel {s₁ s₂ s₃ : Finmap β} (h : Disjoint s₁ s₃) (h' : Disjoint s₂ s₃) :
    s₁ ∪ s₃ = s₂ ∪ s₃ ↔ s₁ = s₂ :=
  ⟨fun h'' => by
    apply ext_lookup
    intro x
    have : (s₁ ∪ s₃).lookup x = (s₂ ∪ s₃).lookup x := h'' ▸ rfl
    by_cases hs₁ : x ∈ s₁
    · rwa [lookup_union_left hs₁, lookup_union_left_of_not_in (h _ hs₁)] at this
    · 

Proof state:
case neg
α : Type u
β : α → Type v
inst✝ : DecidableEq α
s₁ s₂ s₃ : Finmap β
h : Disjoint s₁ s₃
h' : Disjoint s₂ s₃
h'' : s₁ ∪ s₃ = s₂ ∪ s₃
x : α
this : lookup x (s₁ ∪ s₃) = lookup x (s₂ ∪ s₃)
hs₁ : x ∉ s₁
⊢ lookup x s₁ = lookup x s₂

Next tactic:
by_cases hs₂ : x ∈ s₂
theorem union_cancel {s₁ s₂ s₃ : Finmap β} (h : Disjoint s₁ s₃) (h' : Disjoint s₂ s₃) :
    s₁ ∪ s₃ = s₂ ∪ s₃ ↔ s₁ = s₂ :=
  ⟨fun h'' => by
    apply ext_lookup
    intro x
    have : (s₁ ∪ s₃).lookup x = (s₂ ∪ s₃).lookup x := h'' ▸ rfl
    by_cases hs₁ : x ∈ s₁
    · rwa [lookup_union_left hs₁, lookup_union_left_of_not_in (h _ hs₁)] at this
    · by_cases hs₂ : x ∈ s₂
      · 

Proof state:
case pos
α : Type u
β : α → Type v
inst✝ : DecidableEq α
s₁ s₂ s₃ : Finmap β
h : Disjoint s₁ s₃
h' : Disjoint s₂ s₃
h'' : s₁ ∪ s₃ = s₂ ∪ s₃
x : α
this : lookup x (s₁ ∪ s₃) = lookup x (s₂ ∪ s₃)
hs₁ : x ∉ s₁
hs₂ : x ∈ s₂
⊢ lookup x s₁ = lookup x s₂

Next tactic:
rwa [lookup_union_left_of_not_in (h' _ hs₂), lookup_union_left hs₂] at this
theorem union_cancel {s₁ s₂ s₃ : Finmap β} (h : Disjoint s₁ s₃) (h' : Disjoint s₂ s₃) :
    s₁ ∪ s₃ = s₂ ∪ s₃ ↔ s₁ = s₂ :=
  ⟨fun h'' => by
    apply ext_lookup
    intro x
    have : (s₁ ∪ s₃).lookup x = (s₂ ∪ s₃).lookup x := h'' ▸ rfl
    by_cases hs₁ : x ∈ s₁
    · rwa [lookup_union_left hs₁, lookup_union_left_of_not_in (h _ hs₁)] at this
    · by_cases hs₂ : x ∈ s₂
      · rwa [lookup_union_left_of_not_in (h' _ hs₂), lookup_union_left hs₂] at this
      · 

Proof state:
case neg
α : Type u
β : α → Type v
inst✝ : DecidableEq α
s₁ s₂ s₃ : Finmap β
h : Disjoint s₁ s₃
h' : Disjoint s₂ s₃
h'' : s₁ ∪ s₃ = s₂ ∪ s₃
x : α
this : lookup x (s₁ ∪ s₃) = lookup x (s₂ ∪ s₃)
hs₁ : x ∉ s₁
hs₂ : x ∉ s₂
⊢ lookup x s₁ = lookup x s₂

Next tactic:
rw [lookup_eq_none.mpr hs₁, lookup_eq_none.mpr hs₂]
instance hasNatScalar : SMul ℕ (C ⟶ D) :=
  ⟨fun n f =>
    { f := fun i => n • f.f i
      comm' := fun i j _ => by 

Proof state:
ι : Type u_1
V : Type u
inst✝¹ : Category.{v, u} V
inst✝ : Preadditive V
c : ComplexShape ι
C D E : HomologicalComplex V c
f✝ g : C ⟶ D
h k : D ⟶ E
i✝ : ι
n : ℕ
f : C ⟶ D
i j : ι
x✝ : ComplexShape.Rel c i j
⊢ (fun i => n • Hom.f f i) i ≫ d D i j = d C i j ≫ (fun i => n • Hom.f f i) j

Next tactic:
simp [Preadditive.nsmul_comp, Preadditive.comp_nsmul]
instance hasIntScalar : SMul ℤ (C ⟶ D) :=
  ⟨fun n f =>
    { f := fun i => n • f.f i
      comm' := fun i j _ => by 

Proof state:
ι : Type u_1
V : Type u
inst✝¹ : Category.{v, u} V
inst✝ : Preadditive V
c : ComplexShape ι
C D E : HomologicalComplex V c
f✝ g : C ⟶ D
h k : D ⟶ E
i✝ : ι
n : ℤ
f : C ⟶ D
i j : ι
x✝ : ComplexShape.Rel c i j
⊢ (fun i => n • Hom.f f i) i ≫ d D i j = d C i j ≫ (fun i => n • Hom.f f i) j

Next tactic:
simp [Preadditive.zsmul_comp, Preadditive.comp_zsmul]
instance : AddCommGroup (C ⟶ D) :=
  Function.Injective.addCommGroup Hom.f HomologicalComplex.hom_f_injective
    (by 

Proof state:
ι : Type u_1
V : Type u
inst✝¹ : Category.{v, u} V
inst✝ : Preadditive V
c : ComplexShape ι
C D E : HomologicalComplex V c
f g : C ⟶ D
h k : D ⟶ E
i : ι
⊢ 0.f = 0

Next tactic:
aesop_cat
instance : AddCommGroup (C ⟶ D) :=
  Function.Injective.addCommGroup Hom.f HomologicalComplex.hom_f_injective
    (by aesop_cat) (by 

Proof state:
ι : Type u_1
V : Type u
inst✝¹ : Category.{v, u} V
inst✝ : Preadditive V
c : ComplexShape ι
C D E : HomologicalComplex V c
f g : C ⟶ D
h k : D ⟶ E
i : ι
⊢ ∀ (x y : C ⟶ D), (x + y).f = x.f + y.f

Next tactic:
aesop_cat
instance : AddCommGroup (C ⟶ D) :=
  Function.Injective.addCommGroup Hom.f HomologicalComplex.hom_f_injective
    (by aesop_cat) (by aesop_cat) (by 

Proof state:
ι : Type u_1
V : Type u
inst✝¹ : Category.{v, u} V
inst✝ : Preadditive V
c : ComplexShape ι
C D E : HomologicalComplex V c
f g : C ⟶ D
h k : D ⟶ E
i : ι
⊢ ∀ (x : C ⟶ D), (-x).f = -x.f

Next tactic:
aesop_cat
instance : AddCommGroup (C ⟶ D) :=
  Function.Injective.addCommGroup Hom.f HomologicalComplex.hom_f_injective
    (by aesop_cat) (by aesop_cat) (by aesop_cat) (by 

Proof state:
ι : Type u_1
V : Type u
inst✝¹ : Category.{v, u} V
inst✝ : Preadditive V
c : ComplexShape ι
C D E : HomologicalComplex V c
f g : C ⟶ D
h k : D ⟶ E
i : ι
⊢ ∀ (x y : C ⟶ D), (x - y).f = x.f - y.f

Next tactic:
aesop_cat